diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
commit | 3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch) | |
tree | 2e1c188dd7b8d7475cd163de9ae02c428343669b /tests | |
parent | Initial commit. (diff) | |
download | bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.tar.xz bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.zip |
Adding upstream version 1:9.18.19.upstream/1%9.18.19upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
196 files changed, 55432 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..8b5dcbe --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) + +SUBDIRS = libtest isc dns ns isccfg irs +check_PROGRAMS = diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..7a21334 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,809 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = unit-test-driver.sh +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/unit-test-driver.sh.in $(top_srcdir)/Makefile.top +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBUV_CFLAGS) -I$(top_srcdir)/lib/isc +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +SUBDIRS = libtest isc dns ns isccfg irs +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +unit-test-driver.sh: $(top_builddir)/config.status $(srcdir)/unit-test-driver.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +doc: doc-recursive + +doc-am: doc-local + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +test: test-recursive + +test-am: test-local + +uninstall-am: + +unit: unit-recursive + +unit-am: unit-local + +.MAKE: $(am__recursive_targets) check-am install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-generic \ + distclean-libtool distclean-tags distdir doc-am doc-local dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am test-am test-local uninstall uninstall-am unit-am \ + unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/dns/Kdh.+002+18602.key b/tests/dns/Kdh.+002+18602.key new file mode 100644 index 0000000..09b4cf5 --- /dev/null +++ b/tests/dns/Kdh.+002+18602.key @@ -0,0 +1 @@ +dh. IN KEY 0 2 2 AAEBAAAAYIHI/wjtOagNga9GILSoS02IVelgLilPE/TfhtvShsiDAXqb IfxQcj2JkuOnNLs5ttb2WZXWl5/jsSjIxHMwMF2XY4gwt/lwHBf/vgYH r7aIxnKXov1jk9rymTLHGKIOtg== diff --git a/tests/dns/Krsa.+008+29238.key b/tests/dns/Krsa.+008+29238.key new file mode 100644 index 0000000..8a09067 --- /dev/null +++ b/tests/dns/Krsa.+008+29238.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 29235, for rsa. +; Created: 20160819191802 (Fri Aug 19 21:18:02 2016) +; Publish: 20160819191802 (Fri Aug 19 21:18:02 2016) +; Activate: 20160819191802 (Fri Aug 19 21:18:02 2016) +rsa. IN DNSKEY 256 3 8 AwEAAdLT1R3qiqCqll3Xzh2qFMvehQ9FODsPftw5U4UjB3QwnJ/3+dph 9kZBBeaJagUBVYzoArk6XNydpp3HhSCFDcIiepL6r8XAifW3SqI1KCne OD38kSCl/Qm9P0+3CFWokGVubsSQ+3dpQZxqx5bzOXthbuzAr6X+gDUE LAyHtCQNmJ+4ktdCoj3DNYW0z/xLvrcB2Lns7H+/qWnGPL4f3hr7Vbak Oeay+4J4KGdY2LFxJUVts6QrgAA8gz4mV9YIJFP+C4B3b/Z7qgqZRxmT 0pic+fJC5+sq0l8KwavPn0n+HqVuJNvppVKMdTbsmmuk69RFGMjbFkP7 tnCiqC9Zi6s= diff --git a/tests/dns/Makefile.am b/tests/dns/Makefile.am new file mode 100644 index 0000000..7062c60 --- /dev/null +++ b/tests/dns/Makefile.am @@ -0,0 +1,132 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBUV_CFLAGS) \ + $(KRB5_CFLAGS) \ + -DSRCDIR=\"$(abs_srcdir)\" \ + -DBUILDDIR=\"$(abs_builddir)\" \ + -I$(top_srcdir)/lib/dns \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBUV_LIBS) \ + $(LIBDNS_LIBS) + +check_PROGRAMS = \ + acl_test \ + db_test \ + dbdiff_test \ + dbiterator_test \ + dbversion_test \ + dh_test \ + dispatch_test \ + dns64_test \ + dst_test \ + keytable_test \ + name_test \ + nsec3_test \ + nsec3param_test \ + private_test \ + rbt_test \ + rbtdb_test \ + rdata_test \ + rdataset_test \ + rdatasetstats_test \ + resolver_test \ + rsa_test \ + sigs_test \ + time_test \ + tsig_test \ + update_test \ + zonemgr_test \ + zt_test + +CLEANFILES = + +if HAVE_PERL + +check_PROGRAMS += \ + master_test + +EXTRA_master_test_DEPENDENCIES = testdata/master/master12.data testdata/master/master13.data testdata/master/master14.data +CLEANFILES += $(EXTRA_master_test_DEPENDENCIES) + +testdata/master/master12.data: testdata/master/master12.data.in + mkdir -p testdata/master + $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master12.data.in > $@ + +testdata/master/master13.data: testdata/master/master13.data.in + mkdir -p testdata/master + $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master13.data.in > $@ + +testdata/master/master14.data: testdata/master/master14.data.in + mkdir -p testdata/master + $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master14.data.in > $@ + +endif + +if HAVE_GEOIP2 +check_PROGRAMS += \ + geoip_test + +geoip_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(MAXMINDDB_CFLAGS) \ + -DTEST_GEOIP_DATA=\"$(top_srcdir)/bin/tests/system/geoip2/data\" + +geoip_test_LDADD = \ + $(LDADD) \ + $(MAXMINDDB_LIBS) +endif + +if HAVE_DNSTAP +check_PROGRAMS += \ + dnstap_test + +dnstap_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(DNSTAP_CFLAGS) +dnstap_test_LDADD = \ + $(LDADD) \ + $(DNSTAP_LIBS) +endif + +dh_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dst_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rsa_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rdata_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rdata_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +EXTRA_sigs_test_DEPENDENCIES = testdata/master/master18.data +CLEANFILES += $(EXTRA_sigs_test_DEPENDENCIES) + +testdata/master/master18.data: testdata/master/master18.data.in + mkdir -p testdata/master + sed -e 's,@TOP_SRCDIR@,$(abs_srcdir),' < $(srcdir)/testdata/master/master18.data.in > $@ + +EXTRA_DIST = \ + Kdh.+002+18602.key \ + Krsa.+008+29238.key \ + comparekeys \ + mkraw.pl \ + testdata \ + testkeys + +include $(top_srcdir)/Makefile.tests diff --git a/tests/dns/Makefile.in b/tests/dns/Makefile.in new file mode 100644 index 0000000..34e27a8 --- /dev/null +++ b/tests/dns/Makefile.in @@ -0,0 +1,1934 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = acl_test$(EXEEXT) db_test$(EXEEXT) \ + dbdiff_test$(EXEEXT) dbiterator_test$(EXEEXT) \ + dbversion_test$(EXEEXT) dh_test$(EXEEXT) \ + dispatch_test$(EXEEXT) dns64_test$(EXEEXT) dst_test$(EXEEXT) \ + keytable_test$(EXEEXT) name_test$(EXEEXT) nsec3_test$(EXEEXT) \ + nsec3param_test$(EXEEXT) private_test$(EXEEXT) \ + rbt_test$(EXEEXT) rbtdb_test$(EXEEXT) rdata_test$(EXEEXT) \ + rdataset_test$(EXEEXT) rdatasetstats_test$(EXEEXT) \ + resolver_test$(EXEEXT) rsa_test$(EXEEXT) sigs_test$(EXEEXT) \ + time_test$(EXEEXT) tsig_test$(EXEEXT) update_test$(EXEEXT) \ + zonemgr_test$(EXEEXT) zt_test$(EXEEXT) $(am__EXEEXT_1) \ + $(am__EXEEXT_2) $(am__EXEEXT_3) +@HAVE_PERL_TRUE@am__append_2 = \ +@HAVE_PERL_TRUE@ master_test + +@HAVE_PERL_TRUE@am__append_3 = $(EXTRA_master_test_DEPENDENCIES) +@HAVE_GEOIP2_TRUE@am__append_4 = \ +@HAVE_GEOIP2_TRUE@ geoip_test + +@HAVE_DNSTAP_TRUE@am__append_5 = \ +@HAVE_DNSTAP_TRUE@ dnstap_test + +subdir = tests/dns +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_PERL_TRUE@am__EXEEXT_1 = master_test$(EXEEXT) +@HAVE_GEOIP2_TRUE@am__EXEEXT_2 = geoip_test$(EXEEXT) +@HAVE_DNSTAP_TRUE@am__EXEEXT_3 = dnstap_test$(EXEEXT) +acl_test_SOURCES = acl_test.c +acl_test_OBJECTS = acl_test.$(OBJEXT) +acl_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +acl_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +db_test_SOURCES = db_test.c +db_test_OBJECTS = db_test.$(OBJEXT) +db_test_LDADD = $(LDADD) +db_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dbdiff_test_SOURCES = dbdiff_test.c +dbdiff_test_OBJECTS = dbdiff_test.$(OBJEXT) +dbdiff_test_LDADD = $(LDADD) +dbdiff_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dbiterator_test_SOURCES = dbiterator_test.c +dbiterator_test_OBJECTS = dbiterator_test.$(OBJEXT) +dbiterator_test_LDADD = $(LDADD) +dbiterator_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dbversion_test_SOURCES = dbversion_test.c +dbversion_test_OBJECTS = dbversion_test.$(OBJEXT) +dbversion_test_LDADD = $(LDADD) +dbversion_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dh_test_SOURCES = dh_test.c +dh_test_OBJECTS = dh_test-dh_test.$(OBJEXT) +dh_test_LDADD = $(LDADD) +dh_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dispatch_test_SOURCES = dispatch_test.c +dispatch_test_OBJECTS = dispatch_test.$(OBJEXT) +dispatch_test_LDADD = $(LDADD) +dispatch_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dns64_test_SOURCES = dns64_test.c +dns64_test_OBJECTS = dns64_test.$(OBJEXT) +dns64_test_LDADD = $(LDADD) +dns64_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +dnstap_test_SOURCES = dnstap_test.c +dnstap_test_OBJECTS = dnstap_test-dnstap_test.$(OBJEXT) +am__DEPENDENCIES_2 = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +@HAVE_DNSTAP_TRUE@dnstap_test_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@HAVE_DNSTAP_TRUE@ $(am__DEPENDENCIES_1) +dst_test_SOURCES = dst_test.c +dst_test_OBJECTS = dst_test-dst_test.$(OBJEXT) +dst_test_LDADD = $(LDADD) +dst_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +geoip_test_SOURCES = geoip_test.c +geoip_test_OBJECTS = geoip_test-geoip_test.$(OBJEXT) +@HAVE_GEOIP2_TRUE@geoip_test_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@HAVE_GEOIP2_TRUE@ $(am__DEPENDENCIES_1) +keytable_test_SOURCES = keytable_test.c +keytable_test_OBJECTS = keytable_test.$(OBJEXT) +keytable_test_LDADD = $(LDADD) +keytable_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +master_test_SOURCES = master_test.c +master_test_OBJECTS = master_test.$(OBJEXT) +master_test_LDADD = $(LDADD) +master_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +name_test_SOURCES = name_test.c +name_test_OBJECTS = name_test.$(OBJEXT) +name_test_LDADD = $(LDADD) +name_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +nsec3_test_SOURCES = nsec3_test.c +nsec3_test_OBJECTS = nsec3_test.$(OBJEXT) +nsec3_test_LDADD = $(LDADD) +nsec3_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +nsec3param_test_SOURCES = nsec3param_test.c +nsec3param_test_OBJECTS = nsec3param_test.$(OBJEXT) +nsec3param_test_LDADD = $(LDADD) +nsec3param_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +private_test_SOURCES = private_test.c +private_test_OBJECTS = private_test.$(OBJEXT) +private_test_LDADD = $(LDADD) +private_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +rbt_test_SOURCES = rbt_test.c +rbt_test_OBJECTS = rbt_test.$(OBJEXT) +rbt_test_LDADD = $(LDADD) +rbt_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +rbtdb_test_SOURCES = rbtdb_test.c +rbtdb_test_OBJECTS = rbtdb_test.$(OBJEXT) +rbtdb_test_LDADD = $(LDADD) +rbtdb_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +rdata_test_SOURCES = rdata_test.c +rdata_test_OBJECTS = rdata_test-rdata_test.$(OBJEXT) +rdata_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +rdataset_test_SOURCES = rdataset_test.c +rdataset_test_OBJECTS = rdataset_test.$(OBJEXT) +rdataset_test_LDADD = $(LDADD) +rdataset_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +rdatasetstats_test_SOURCES = rdatasetstats_test.c +rdatasetstats_test_OBJECTS = rdatasetstats_test.$(OBJEXT) +rdatasetstats_test_LDADD = $(LDADD) +rdatasetstats_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +resolver_test_SOURCES = resolver_test.c +resolver_test_OBJECTS = resolver_test.$(OBJEXT) +resolver_test_LDADD = $(LDADD) +resolver_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +rsa_test_SOURCES = rsa_test.c +rsa_test_OBJECTS = rsa_test-rsa_test.$(OBJEXT) +rsa_test_LDADD = $(LDADD) +rsa_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +sigs_test_SOURCES = sigs_test.c +sigs_test_OBJECTS = sigs_test.$(OBJEXT) +sigs_test_LDADD = $(LDADD) +sigs_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +time_test_SOURCES = time_test.c +time_test_OBJECTS = time_test.$(OBJEXT) +time_test_LDADD = $(LDADD) +time_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +tsig_test_SOURCES = tsig_test.c +tsig_test_OBJECTS = tsig_test.$(OBJEXT) +tsig_test_LDADD = $(LDADD) +tsig_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +update_test_SOURCES = update_test.c +update_test_OBJECTS = update_test.$(OBJEXT) +update_test_LDADD = $(LDADD) +update_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +zonemgr_test_SOURCES = zonemgr_test.c +zonemgr_test_OBJECTS = zonemgr_test.$(OBJEXT) +zonemgr_test_LDADD = $(LDADD) +zonemgr_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +zt_test_SOURCES = zt_test.c +zt_test_OBJECTS = zt_test.$(OBJEXT) +zt_test_LDADD = $(LDADD) +zt_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(LIBDNS_LIBS) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/acl_test.Po ./$(DEPDIR)/db_test.Po \ + ./$(DEPDIR)/dbdiff_test.Po ./$(DEPDIR)/dbiterator_test.Po \ + ./$(DEPDIR)/dbversion_test.Po ./$(DEPDIR)/dh_test-dh_test.Po \ + ./$(DEPDIR)/dispatch_test.Po ./$(DEPDIR)/dns64_test.Po \ + ./$(DEPDIR)/dnstap_test-dnstap_test.Po \ + ./$(DEPDIR)/dst_test-dst_test.Po \ + ./$(DEPDIR)/geoip_test-geoip_test.Po \ + ./$(DEPDIR)/keytable_test.Po ./$(DEPDIR)/master_test.Po \ + ./$(DEPDIR)/name_test.Po ./$(DEPDIR)/nsec3_test.Po \ + ./$(DEPDIR)/nsec3param_test.Po ./$(DEPDIR)/private_test.Po \ + ./$(DEPDIR)/rbt_test.Po ./$(DEPDIR)/rbtdb_test.Po \ + ./$(DEPDIR)/rdata_test-rdata_test.Po \ + ./$(DEPDIR)/rdataset_test.Po ./$(DEPDIR)/rdatasetstats_test.Po \ + ./$(DEPDIR)/resolver_test.Po ./$(DEPDIR)/rsa_test-rsa_test.Po \ + ./$(DEPDIR)/sigs_test.Po ./$(DEPDIR)/time_test.Po \ + ./$(DEPDIR)/tsig_test.Po ./$(DEPDIR)/update_test.Po \ + ./$(DEPDIR)/zonemgr_test.Po ./$(DEPDIR)/zt_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = acl_test.c db_test.c dbdiff_test.c dbiterator_test.c \ + dbversion_test.c dh_test.c dispatch_test.c dns64_test.c \ + dnstap_test.c dst_test.c geoip_test.c keytable_test.c \ + master_test.c name_test.c nsec3_test.c nsec3param_test.c \ + private_test.c rbt_test.c rbtdb_test.c rdata_test.c \ + rdataset_test.c rdatasetstats_test.c resolver_test.c \ + rsa_test.c sigs_test.c time_test.c tsig_test.c update_test.c \ + zonemgr_test.c zt_test.c +DIST_SOURCES = acl_test.c db_test.c dbdiff_test.c dbiterator_test.c \ + dbversion_test.c dh_test.c dispatch_test.c dns64_test.c \ + dnstap_test.c dst_test.c geoip_test.c keytable_test.c \ + master_test.c name_test.c nsec3_test.c nsec3param_test.c \ + private_test.c rbt_test.c rbtdb_test.c rdata_test.c \ + rdataset_test.c rdatasetstats_test.c resolver_test.c \ + rsa_test.c sigs_test.c time_test.c tsig_test.c update_test.c \ + zonemgr_test.c zt_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBUV_CFLAGS) $(KRB5_CFLAGS) -DSRCDIR=\"$(abs_srcdir)\" \ + -DBUILDDIR=\"$(abs_builddir)\" -I$(top_srcdir)/lib/dns \ + -I$(top_srcdir)/lib/isc $(CMOCKA_CFLAGS) \ + -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBUV_LIBS) $(LIBDNS_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +CLEANFILES = $(am__append_3) $(EXTRA_sigs_test_DEPENDENCIES) +@HAVE_PERL_TRUE@EXTRA_master_test_DEPENDENCIES = testdata/master/master12.data testdata/master/master13.data testdata/master/master14.data +@HAVE_GEOIP2_TRUE@geoip_test_CPPFLAGS = \ +@HAVE_GEOIP2_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_GEOIP2_TRUE@ $(MAXMINDDB_CFLAGS) \ +@HAVE_GEOIP2_TRUE@ -DTEST_GEOIP_DATA=\"$(top_srcdir)/bin/tests/system/geoip2/data\" + +@HAVE_GEOIP2_TRUE@geoip_test_LDADD = \ +@HAVE_GEOIP2_TRUE@ $(LDADD) \ +@HAVE_GEOIP2_TRUE@ $(MAXMINDDB_LIBS) + +@HAVE_DNSTAP_TRUE@dnstap_test_CPPFLAGS = \ +@HAVE_DNSTAP_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_DNSTAP_TRUE@ $(DNSTAP_CFLAGS) + +@HAVE_DNSTAP_TRUE@dnstap_test_LDADD = \ +@HAVE_DNSTAP_TRUE@ $(LDADD) \ +@HAVE_DNSTAP_TRUE@ $(DNSTAP_LIBS) + +dh_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dst_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rsa_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rdata_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +rdata_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +EXTRA_sigs_test_DEPENDENCIES = testdata/master/master18.data +EXTRA_DIST = \ + Kdh.+002+18602.key \ + Krsa.+008+29238.key \ + comparekeys \ + mkraw.pl \ + testdata \ + testkeys + +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/dns/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/dns/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +acl_test$(EXEEXT): $(acl_test_OBJECTS) $(acl_test_DEPENDENCIES) $(EXTRA_acl_test_DEPENDENCIES) + @rm -f acl_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(acl_test_OBJECTS) $(acl_test_LDADD) $(LIBS) + +db_test$(EXEEXT): $(db_test_OBJECTS) $(db_test_DEPENDENCIES) $(EXTRA_db_test_DEPENDENCIES) + @rm -f db_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(db_test_OBJECTS) $(db_test_LDADD) $(LIBS) + +dbdiff_test$(EXEEXT): $(dbdiff_test_OBJECTS) $(dbdiff_test_DEPENDENCIES) $(EXTRA_dbdiff_test_DEPENDENCIES) + @rm -f dbdiff_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dbdiff_test_OBJECTS) $(dbdiff_test_LDADD) $(LIBS) + +dbiterator_test$(EXEEXT): $(dbiterator_test_OBJECTS) $(dbiterator_test_DEPENDENCIES) $(EXTRA_dbiterator_test_DEPENDENCIES) + @rm -f dbiterator_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dbiterator_test_OBJECTS) $(dbiterator_test_LDADD) $(LIBS) + +dbversion_test$(EXEEXT): $(dbversion_test_OBJECTS) $(dbversion_test_DEPENDENCIES) $(EXTRA_dbversion_test_DEPENDENCIES) + @rm -f dbversion_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dbversion_test_OBJECTS) $(dbversion_test_LDADD) $(LIBS) + +dh_test$(EXEEXT): $(dh_test_OBJECTS) $(dh_test_DEPENDENCIES) $(EXTRA_dh_test_DEPENDENCIES) + @rm -f dh_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dh_test_OBJECTS) $(dh_test_LDADD) $(LIBS) + +dispatch_test$(EXEEXT): $(dispatch_test_OBJECTS) $(dispatch_test_DEPENDENCIES) $(EXTRA_dispatch_test_DEPENDENCIES) + @rm -f dispatch_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dispatch_test_OBJECTS) $(dispatch_test_LDADD) $(LIBS) + +dns64_test$(EXEEXT): $(dns64_test_OBJECTS) $(dns64_test_DEPENDENCIES) $(EXTRA_dns64_test_DEPENDENCIES) + @rm -f dns64_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dns64_test_OBJECTS) $(dns64_test_LDADD) $(LIBS) + +dnstap_test$(EXEEXT): $(dnstap_test_OBJECTS) $(dnstap_test_DEPENDENCIES) $(EXTRA_dnstap_test_DEPENDENCIES) + @rm -f dnstap_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnstap_test_OBJECTS) $(dnstap_test_LDADD) $(LIBS) + +dst_test$(EXEEXT): $(dst_test_OBJECTS) $(dst_test_DEPENDENCIES) $(EXTRA_dst_test_DEPENDENCIES) + @rm -f dst_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dst_test_OBJECTS) $(dst_test_LDADD) $(LIBS) + +geoip_test$(EXEEXT): $(geoip_test_OBJECTS) $(geoip_test_DEPENDENCIES) $(EXTRA_geoip_test_DEPENDENCIES) + @rm -f geoip_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(geoip_test_OBJECTS) $(geoip_test_LDADD) $(LIBS) + +keytable_test$(EXEEXT): $(keytable_test_OBJECTS) $(keytable_test_DEPENDENCIES) $(EXTRA_keytable_test_DEPENDENCIES) + @rm -f keytable_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(keytable_test_OBJECTS) $(keytable_test_LDADD) $(LIBS) + +master_test$(EXEEXT): $(master_test_OBJECTS) $(master_test_DEPENDENCIES) $(EXTRA_master_test_DEPENDENCIES) + @rm -f master_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(master_test_OBJECTS) $(master_test_LDADD) $(LIBS) + +name_test$(EXEEXT): $(name_test_OBJECTS) $(name_test_DEPENDENCIES) $(EXTRA_name_test_DEPENDENCIES) + @rm -f name_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(name_test_OBJECTS) $(name_test_LDADD) $(LIBS) + +nsec3_test$(EXEEXT): $(nsec3_test_OBJECTS) $(nsec3_test_DEPENDENCIES) $(EXTRA_nsec3_test_DEPENDENCIES) + @rm -f nsec3_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nsec3_test_OBJECTS) $(nsec3_test_LDADD) $(LIBS) + +nsec3param_test$(EXEEXT): $(nsec3param_test_OBJECTS) $(nsec3param_test_DEPENDENCIES) $(EXTRA_nsec3param_test_DEPENDENCIES) + @rm -f nsec3param_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nsec3param_test_OBJECTS) $(nsec3param_test_LDADD) $(LIBS) + +private_test$(EXEEXT): $(private_test_OBJECTS) $(private_test_DEPENDENCIES) $(EXTRA_private_test_DEPENDENCIES) + @rm -f private_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(private_test_OBJECTS) $(private_test_LDADD) $(LIBS) + +rbt_test$(EXEEXT): $(rbt_test_OBJECTS) $(rbt_test_DEPENDENCIES) $(EXTRA_rbt_test_DEPENDENCIES) + @rm -f rbt_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rbt_test_OBJECTS) $(rbt_test_LDADD) $(LIBS) + +rbtdb_test$(EXEEXT): $(rbtdb_test_OBJECTS) $(rbtdb_test_DEPENDENCIES) $(EXTRA_rbtdb_test_DEPENDENCIES) + @rm -f rbtdb_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rbtdb_test_OBJECTS) $(rbtdb_test_LDADD) $(LIBS) + +rdata_test$(EXEEXT): $(rdata_test_OBJECTS) $(rdata_test_DEPENDENCIES) $(EXTRA_rdata_test_DEPENDENCIES) + @rm -f rdata_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rdata_test_OBJECTS) $(rdata_test_LDADD) $(LIBS) + +rdataset_test$(EXEEXT): $(rdataset_test_OBJECTS) $(rdataset_test_DEPENDENCIES) $(EXTRA_rdataset_test_DEPENDENCIES) + @rm -f rdataset_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rdataset_test_OBJECTS) $(rdataset_test_LDADD) $(LIBS) + +rdatasetstats_test$(EXEEXT): $(rdatasetstats_test_OBJECTS) $(rdatasetstats_test_DEPENDENCIES) $(EXTRA_rdatasetstats_test_DEPENDENCIES) + @rm -f rdatasetstats_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rdatasetstats_test_OBJECTS) $(rdatasetstats_test_LDADD) $(LIBS) + +resolver_test$(EXEEXT): $(resolver_test_OBJECTS) $(resolver_test_DEPENDENCIES) $(EXTRA_resolver_test_DEPENDENCIES) + @rm -f resolver_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(resolver_test_OBJECTS) $(resolver_test_LDADD) $(LIBS) + +rsa_test$(EXEEXT): $(rsa_test_OBJECTS) $(rsa_test_DEPENDENCIES) $(EXTRA_rsa_test_DEPENDENCIES) + @rm -f rsa_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rsa_test_OBJECTS) $(rsa_test_LDADD) $(LIBS) + +sigs_test$(EXEEXT): $(sigs_test_OBJECTS) $(sigs_test_DEPENDENCIES) $(EXTRA_sigs_test_DEPENDENCIES) + @rm -f sigs_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sigs_test_OBJECTS) $(sigs_test_LDADD) $(LIBS) + +time_test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES) $(EXTRA_time_test_DEPENDENCIES) + @rm -f time_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS) + +tsig_test$(EXEEXT): $(tsig_test_OBJECTS) $(tsig_test_DEPENDENCIES) $(EXTRA_tsig_test_DEPENDENCIES) + @rm -f tsig_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tsig_test_OBJECTS) $(tsig_test_LDADD) $(LIBS) + +update_test$(EXEEXT): $(update_test_OBJECTS) $(update_test_DEPENDENCIES) $(EXTRA_update_test_DEPENDENCIES) + @rm -f update_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(update_test_OBJECTS) $(update_test_LDADD) $(LIBS) + +zonemgr_test$(EXEEXT): $(zonemgr_test_OBJECTS) $(zonemgr_test_DEPENDENCIES) $(EXTRA_zonemgr_test_DEPENDENCIES) + @rm -f zonemgr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(zonemgr_test_OBJECTS) $(zonemgr_test_LDADD) $(LIBS) + +zt_test$(EXEEXT): $(zt_test_OBJECTS) $(zt_test_DEPENDENCIES) $(EXTRA_zt_test_DEPENDENCIES) + @rm -f zt_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(zt_test_OBJECTS) $(zt_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbdiff_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbiterator_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbversion_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dh_test-dh_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dispatch_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns64_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnstap_test-dnstap_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dst_test-dst_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoip_test-geoip_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keytable_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/name_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3param_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/private_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbtdb_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdata_test-rdata_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdataset_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdatasetstats_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolver_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa_test-rsa_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigs_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zonemgr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zt_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +dh_test-dh_test.o: dh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dh_test-dh_test.o -MD -MP -MF $(DEPDIR)/dh_test-dh_test.Tpo -c -o dh_test-dh_test.o `test -f 'dh_test.c' || echo '$(srcdir)/'`dh_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dh_test-dh_test.Tpo $(DEPDIR)/dh_test-dh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dh_test.c' object='dh_test-dh_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dh_test-dh_test.o `test -f 'dh_test.c' || echo '$(srcdir)/'`dh_test.c + +dh_test-dh_test.obj: dh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dh_test-dh_test.obj -MD -MP -MF $(DEPDIR)/dh_test-dh_test.Tpo -c -o dh_test-dh_test.obj `if test -f 'dh_test.c'; then $(CYGPATH_W) 'dh_test.c'; else $(CYGPATH_W) '$(srcdir)/dh_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dh_test-dh_test.Tpo $(DEPDIR)/dh_test-dh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dh_test.c' object='dh_test-dh_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dh_test-dh_test.obj `if test -f 'dh_test.c'; then $(CYGPATH_W) 'dh_test.c'; else $(CYGPATH_W) '$(srcdir)/dh_test.c'; fi` + +dnstap_test-dnstap_test.o: dnstap_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnstap_test-dnstap_test.o -MD -MP -MF $(DEPDIR)/dnstap_test-dnstap_test.Tpo -c -o dnstap_test-dnstap_test.o `test -f 'dnstap_test.c' || echo '$(srcdir)/'`dnstap_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnstap_test-dnstap_test.Tpo $(DEPDIR)/dnstap_test-dnstap_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnstap_test.c' object='dnstap_test-dnstap_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnstap_test-dnstap_test.o `test -f 'dnstap_test.c' || echo '$(srcdir)/'`dnstap_test.c + +dnstap_test-dnstap_test.obj: dnstap_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnstap_test-dnstap_test.obj -MD -MP -MF $(DEPDIR)/dnstap_test-dnstap_test.Tpo -c -o dnstap_test-dnstap_test.obj `if test -f 'dnstap_test.c'; then $(CYGPATH_W) 'dnstap_test.c'; else $(CYGPATH_W) '$(srcdir)/dnstap_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnstap_test-dnstap_test.Tpo $(DEPDIR)/dnstap_test-dnstap_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnstap_test.c' object='dnstap_test-dnstap_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnstap_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnstap_test-dnstap_test.obj `if test -f 'dnstap_test.c'; then $(CYGPATH_W) 'dnstap_test.c'; else $(CYGPATH_W) '$(srcdir)/dnstap_test.c'; fi` + +dst_test-dst_test.o: dst_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dst_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dst_test-dst_test.o -MD -MP -MF $(DEPDIR)/dst_test-dst_test.Tpo -c -o dst_test-dst_test.o `test -f 'dst_test.c' || echo '$(srcdir)/'`dst_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dst_test-dst_test.Tpo $(DEPDIR)/dst_test-dst_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dst_test.c' object='dst_test-dst_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dst_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dst_test-dst_test.o `test -f 'dst_test.c' || echo '$(srcdir)/'`dst_test.c + +dst_test-dst_test.obj: dst_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dst_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dst_test-dst_test.obj -MD -MP -MF $(DEPDIR)/dst_test-dst_test.Tpo -c -o dst_test-dst_test.obj `if test -f 'dst_test.c'; then $(CYGPATH_W) 'dst_test.c'; else $(CYGPATH_W) '$(srcdir)/dst_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dst_test-dst_test.Tpo $(DEPDIR)/dst_test-dst_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dst_test.c' object='dst_test-dst_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dst_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dst_test-dst_test.obj `if test -f 'dst_test.c'; then $(CYGPATH_W) 'dst_test.c'; else $(CYGPATH_W) '$(srcdir)/dst_test.c'; fi` + +geoip_test-geoip_test.o: geoip_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(geoip_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT geoip_test-geoip_test.o -MD -MP -MF $(DEPDIR)/geoip_test-geoip_test.Tpo -c -o geoip_test-geoip_test.o `test -f 'geoip_test.c' || echo '$(srcdir)/'`geoip_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/geoip_test-geoip_test.Tpo $(DEPDIR)/geoip_test-geoip_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='geoip_test.c' object='geoip_test-geoip_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(geoip_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o geoip_test-geoip_test.o `test -f 'geoip_test.c' || echo '$(srcdir)/'`geoip_test.c + +geoip_test-geoip_test.obj: geoip_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(geoip_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT geoip_test-geoip_test.obj -MD -MP -MF $(DEPDIR)/geoip_test-geoip_test.Tpo -c -o geoip_test-geoip_test.obj `if test -f 'geoip_test.c'; then $(CYGPATH_W) 'geoip_test.c'; else $(CYGPATH_W) '$(srcdir)/geoip_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/geoip_test-geoip_test.Tpo $(DEPDIR)/geoip_test-geoip_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='geoip_test.c' object='geoip_test-geoip_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(geoip_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o geoip_test-geoip_test.obj `if test -f 'geoip_test.c'; then $(CYGPATH_W) 'geoip_test.c'; else $(CYGPATH_W) '$(srcdir)/geoip_test.c'; fi` + +rdata_test-rdata_test.o: rdata_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rdata_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_test-rdata_test.o -MD -MP -MF $(DEPDIR)/rdata_test-rdata_test.Tpo -c -o rdata_test-rdata_test.o `test -f 'rdata_test.c' || echo '$(srcdir)/'`rdata_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rdata_test-rdata_test.Tpo $(DEPDIR)/rdata_test-rdata_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdata_test.c' object='rdata_test-rdata_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rdata_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_test-rdata_test.o `test -f 'rdata_test.c' || echo '$(srcdir)/'`rdata_test.c + +rdata_test-rdata_test.obj: rdata_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rdata_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_test-rdata_test.obj -MD -MP -MF $(DEPDIR)/rdata_test-rdata_test.Tpo -c -o rdata_test-rdata_test.obj `if test -f 'rdata_test.c'; then $(CYGPATH_W) 'rdata_test.c'; else $(CYGPATH_W) '$(srcdir)/rdata_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rdata_test-rdata_test.Tpo $(DEPDIR)/rdata_test-rdata_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdata_test.c' object='rdata_test-rdata_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rdata_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_test-rdata_test.obj `if test -f 'rdata_test.c'; then $(CYGPATH_W) 'rdata_test.c'; else $(CYGPATH_W) '$(srcdir)/rdata_test.c'; fi` + +rsa_test-rsa_test.o: rsa_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsa_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsa_test-rsa_test.o -MD -MP -MF $(DEPDIR)/rsa_test-rsa_test.Tpo -c -o rsa_test-rsa_test.o `test -f 'rsa_test.c' || echo '$(srcdir)/'`rsa_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsa_test-rsa_test.Tpo $(DEPDIR)/rsa_test-rsa_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsa_test.c' object='rsa_test-rsa_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsa_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsa_test-rsa_test.o `test -f 'rsa_test.c' || echo '$(srcdir)/'`rsa_test.c + +rsa_test-rsa_test.obj: rsa_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsa_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsa_test-rsa_test.obj -MD -MP -MF $(DEPDIR)/rsa_test-rsa_test.Tpo -c -o rsa_test-rsa_test.obj `if test -f 'rsa_test.c'; then $(CYGPATH_W) 'rsa_test.c'; else $(CYGPATH_W) '$(srcdir)/rsa_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsa_test-rsa_test.Tpo $(DEPDIR)/rsa_test-rsa_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsa_test.c' object='rsa_test-rsa_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsa_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsa_test-rsa_test.obj `if test -f 'rsa_test.c'; then $(CYGPATH_W) 'rsa_test.c'; else $(CYGPATH_W) '$(srcdir)/rsa_test.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +acl_test.log: acl_test$(EXEEXT) + @p='acl_test$(EXEEXT)'; \ + b='acl_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +db_test.log: db_test$(EXEEXT) + @p='db_test$(EXEEXT)'; \ + b='db_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dbdiff_test.log: dbdiff_test$(EXEEXT) + @p='dbdiff_test$(EXEEXT)'; \ + b='dbdiff_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dbiterator_test.log: dbiterator_test$(EXEEXT) + @p='dbiterator_test$(EXEEXT)'; \ + b='dbiterator_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dbversion_test.log: dbversion_test$(EXEEXT) + @p='dbversion_test$(EXEEXT)'; \ + b='dbversion_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dh_test.log: dh_test$(EXEEXT) + @p='dh_test$(EXEEXT)'; \ + b='dh_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dispatch_test.log: dispatch_test$(EXEEXT) + @p='dispatch_test$(EXEEXT)'; \ + b='dispatch_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dns64_test.log: dns64_test$(EXEEXT) + @p='dns64_test$(EXEEXT)'; \ + b='dns64_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dst_test.log: dst_test$(EXEEXT) + @p='dst_test$(EXEEXT)'; \ + b='dst_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +keytable_test.log: keytable_test$(EXEEXT) + @p='keytable_test$(EXEEXT)'; \ + b='keytable_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +name_test.log: name_test$(EXEEXT) + @p='name_test$(EXEEXT)'; \ + b='name_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nsec3_test.log: nsec3_test$(EXEEXT) + @p='nsec3_test$(EXEEXT)'; \ + b='nsec3_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nsec3param_test.log: nsec3param_test$(EXEEXT) + @p='nsec3param_test$(EXEEXT)'; \ + b='nsec3param_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +private_test.log: private_test$(EXEEXT) + @p='private_test$(EXEEXT)'; \ + b='private_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rbt_test.log: rbt_test$(EXEEXT) + @p='rbt_test$(EXEEXT)'; \ + b='rbt_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rbtdb_test.log: rbtdb_test$(EXEEXT) + @p='rbtdb_test$(EXEEXT)'; \ + b='rbtdb_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rdata_test.log: rdata_test$(EXEEXT) + @p='rdata_test$(EXEEXT)'; \ + b='rdata_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rdataset_test.log: rdataset_test$(EXEEXT) + @p='rdataset_test$(EXEEXT)'; \ + b='rdataset_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rdatasetstats_test.log: rdatasetstats_test$(EXEEXT) + @p='rdatasetstats_test$(EXEEXT)'; \ + b='rdatasetstats_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +resolver_test.log: resolver_test$(EXEEXT) + @p='resolver_test$(EXEEXT)'; \ + b='resolver_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rsa_test.log: rsa_test$(EXEEXT) + @p='rsa_test$(EXEEXT)'; \ + b='rsa_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sigs_test.log: sigs_test$(EXEEXT) + @p='sigs_test$(EXEEXT)'; \ + b='sigs_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +time_test.log: time_test$(EXEEXT) + @p='time_test$(EXEEXT)'; \ + b='time_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tsig_test.log: tsig_test$(EXEEXT) + @p='tsig_test$(EXEEXT)'; \ + b='tsig_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +update_test.log: update_test$(EXEEXT) + @p='update_test$(EXEEXT)'; \ + b='update_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +zonemgr_test.log: zonemgr_test$(EXEEXT) + @p='zonemgr_test$(EXEEXT)'; \ + b='zonemgr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +zt_test.log: zt_test$(EXEEXT) + @p='zt_test$(EXEEXT)'; \ + b='zt_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +master_test.log: master_test$(EXEEXT) + @p='master_test$(EXEEXT)'; \ + b='master_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +geoip_test.log: geoip_test$(EXEEXT) + @p='geoip_test$(EXEEXT)'; \ + b='geoip_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dnstap_test.log: dnstap_test$(EXEEXT) + @p='dnstap_test$(EXEEXT)'; \ + b='dnstap_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/acl_test.Po + -rm -f ./$(DEPDIR)/db_test.Po + -rm -f ./$(DEPDIR)/dbdiff_test.Po + -rm -f ./$(DEPDIR)/dbiterator_test.Po + -rm -f ./$(DEPDIR)/dbversion_test.Po + -rm -f ./$(DEPDIR)/dh_test-dh_test.Po + -rm -f ./$(DEPDIR)/dispatch_test.Po + -rm -f ./$(DEPDIR)/dns64_test.Po + -rm -f ./$(DEPDIR)/dnstap_test-dnstap_test.Po + -rm -f ./$(DEPDIR)/dst_test-dst_test.Po + -rm -f ./$(DEPDIR)/geoip_test-geoip_test.Po + -rm -f ./$(DEPDIR)/keytable_test.Po + -rm -f ./$(DEPDIR)/master_test.Po + -rm -f ./$(DEPDIR)/name_test.Po + -rm -f ./$(DEPDIR)/nsec3_test.Po + -rm -f ./$(DEPDIR)/nsec3param_test.Po + -rm -f ./$(DEPDIR)/private_test.Po + -rm -f ./$(DEPDIR)/rbt_test.Po + -rm -f ./$(DEPDIR)/rbtdb_test.Po + -rm -f ./$(DEPDIR)/rdata_test-rdata_test.Po + -rm -f ./$(DEPDIR)/rdataset_test.Po + -rm -f ./$(DEPDIR)/rdatasetstats_test.Po + -rm -f ./$(DEPDIR)/resolver_test.Po + -rm -f ./$(DEPDIR)/rsa_test-rsa_test.Po + -rm -f ./$(DEPDIR)/sigs_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/tsig_test.Po + -rm -f ./$(DEPDIR)/update_test.Po + -rm -f ./$(DEPDIR)/zonemgr_test.Po + -rm -f ./$(DEPDIR)/zt_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/acl_test.Po + -rm -f ./$(DEPDIR)/db_test.Po + -rm -f ./$(DEPDIR)/dbdiff_test.Po + -rm -f ./$(DEPDIR)/dbiterator_test.Po + -rm -f ./$(DEPDIR)/dbversion_test.Po + -rm -f ./$(DEPDIR)/dh_test-dh_test.Po + -rm -f ./$(DEPDIR)/dispatch_test.Po + -rm -f ./$(DEPDIR)/dns64_test.Po + -rm -f ./$(DEPDIR)/dnstap_test-dnstap_test.Po + -rm -f ./$(DEPDIR)/dst_test-dst_test.Po + -rm -f ./$(DEPDIR)/geoip_test-geoip_test.Po + -rm -f ./$(DEPDIR)/keytable_test.Po + -rm -f ./$(DEPDIR)/master_test.Po + -rm -f ./$(DEPDIR)/name_test.Po + -rm -f ./$(DEPDIR)/nsec3_test.Po + -rm -f ./$(DEPDIR)/nsec3param_test.Po + -rm -f ./$(DEPDIR)/private_test.Po + -rm -f ./$(DEPDIR)/rbt_test.Po + -rm -f ./$(DEPDIR)/rbtdb_test.Po + -rm -f ./$(DEPDIR)/rdata_test-rdata_test.Po + -rm -f ./$(DEPDIR)/rdataset_test.Po + -rm -f ./$(DEPDIR)/rdatasetstats_test.Po + -rm -f ./$(DEPDIR)/resolver_test.Po + -rm -f ./$(DEPDIR)/rsa_test-rsa_test.Po + -rm -f ./$(DEPDIR)/sigs_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/tsig_test.Po + -rm -f ./$(DEPDIR)/update_test.Po + -rm -f ./$(DEPDIR)/zonemgr_test.Po + -rm -f ./$(DEPDIR)/zt_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +@HAVE_PERL_TRUE@testdata/master/master12.data: testdata/master/master12.data.in +@HAVE_PERL_TRUE@ mkdir -p testdata/master +@HAVE_PERL_TRUE@ $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master12.data.in > $@ + +@HAVE_PERL_TRUE@testdata/master/master13.data: testdata/master/master13.data.in +@HAVE_PERL_TRUE@ mkdir -p testdata/master +@HAVE_PERL_TRUE@ $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master13.data.in > $@ + +@HAVE_PERL_TRUE@testdata/master/master14.data: testdata/master/master14.data.in +@HAVE_PERL_TRUE@ mkdir -p testdata/master +@HAVE_PERL_TRUE@ $(PERL) -w $(srcdir)/mkraw.pl < $(srcdir)/testdata/master/master14.data.in > $@ + +testdata/master/master18.data: testdata/master/master18.data.in + mkdir -p testdata/master + sed -e 's,@TOP_SRCDIR@,$(abs_srcdir),' < $(srcdir)/testdata/master/master18.data.in > $@ + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/dns/acl_test.c b/tests/dns/acl_test.c new file mode 100644 index 0000000..bb454b6 --- /dev/null +++ b/tests/dns/acl_test.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/print.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/acl.h> + +#include <tests/dns.h> + +#define BUFLEN 255 +#define BIGBUFLEN (70 * 1024) +#define TEST_ORIGIN "test" + +/* test that dns_acl_isinsecure works */ +ISC_RUN_TEST_IMPL(dns_acl_isinsecure) { + isc_result_t result; + dns_acl_t *any = NULL; + dns_acl_t *none = NULL; + dns_acl_t *notnone = NULL; + dns_acl_t *notany = NULL; +#if defined(HAVE_GEOIP2) + dns_acl_t *geoip = NULL; + dns_acl_t *notgeoip = NULL; + dns_aclelement_t *de; +#endif /* HAVE_GEOIP2 */ + + UNUSED(state); + + result = dns_acl_any(mctx, &any); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_none(mctx, &none); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬none); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_create(mctx, 1, ¬any); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notnone, none, false); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notany, any, false); + assert_int_equal(result, ISC_R_SUCCESS); + +#if defined(HAVE_GEOIP2) + result = dns_acl_create(mctx, 1, &geoip); + assert_int_equal(result, ISC_R_SUCCESS); + + de = geoip->elements; + assert_non_null(de); + strlcpy(de->geoip_elem.as_string, "AU", + sizeof(de->geoip_elem.as_string)); + de->geoip_elem.subtype = dns_geoip_country_code; + de->type = dns_aclelementtype_geoip; + de->negative = false; + assert_true(geoip->length < geoip->alloc); + dns_acl_node_count(geoip)++; + de->node_num = dns_acl_node_count(geoip); + geoip->length++; + + result = dns_acl_create(mctx, 1, ¬geoip); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_acl_merge(notgeoip, geoip, false); + assert_int_equal(result, ISC_R_SUCCESS); +#endif /* HAVE_GEOIP2 */ + + assert_true(dns_acl_isinsecure(any)); /* any; */ + assert_false(dns_acl_isinsecure(none)); /* none; */ + assert_false(dns_acl_isinsecure(notany)); /* !any; */ + assert_false(dns_acl_isinsecure(notnone)); /* !none; */ + +#if defined(HAVE_GEOIP2) + assert_true(dns_acl_isinsecure(geoip)); /* geoip; */ + assert_false(dns_acl_isinsecure(notgeoip)); /* !geoip; */ +#endif /* HAVE_GEOIP2 */ + + dns_acl_detach(&any); + dns_acl_detach(&none); + dns_acl_detach(¬any); + dns_acl_detach(¬none); +#if defined(HAVE_GEOIP2) + dns_acl_detach(&geoip); + dns_acl_detach(¬geoip); +#endif /* HAVE_GEOIP2 */ +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(dns_acl_isinsecure) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/comparekeys/Kexample-d.+008+53461.key b/tests/dns/comparekeys/Kexample-d.+008+53461.key new file mode 100644 index 0000000..5c43165 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-d.+008+53461.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 53461, for example-d. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example-d. IN DNSKEY 256 3 8 AwEAAaKYSOPDzZvfue5sU71xPCJKJpB5kZGl4vTp3OI8W+nN1YFtmVe2 2gM666AEutDAEB7cLkyoKCOH0+4Lh1ucPr6OmdWkHfk7uZv58eH0kOAV tNz2xhEF/YHSD7cnBEU9g0knGwpWuzSJKRhGhNoaVus9g1MaAn8efptz HIduIwgAeXV3BDCUpY6HbpwjDxOGCzCUYDRgcex37kYuCyW0PvlO5FQ0 DT0LpjcgBmIBpXol7sYpmKdOKJrm4x2lwGntr4K+bCdNYI2PRPJjPqAf jlvIvJylGUaqFJasw7PSMQIkgcQ4OQXVrhE8uGLdYvP1cusLuROIjdYp Pdqc5K9lCQE= diff --git a/tests/dns/comparekeys/Kexample-d.+008+53461.private b/tests/dns/comparekeys/Kexample-d.+008+53461.private new file mode 100644 index 0000000..a693428 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-d.+008+53461.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: ophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2ZV7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7kVDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN1ik92pzkr2UJAQ== +PublicExponent: AQAB +PrivateExponent: AhR3VvVoV6OGOjiiNUt728hidEMoX4PJWtHNWqinyRek5tSnqgaXeKC3NuU0mUIjDvBps9oH4lK3yNa5fBr/nodwP4wNyTd3obR/z6JcLersxJjHi4nYX2ju8vjdsBSIulNudqlrsPhLJe0+Tff3FRfClSQmQ/JtakHo4lIx8zxiOJY8aWFeHGdWJDkAf6NStt3eVYyOyAwISfv3muaGPZKShiIOfLyTvqFqzwYFgdTWmvFqTdwgjIMc5XAwqw73WP2BPCN+fdCiMtrw0fCrhWzw/gfMJBHdOPH0diUZysAJhM0vdVKQzEi/g3YOo00fahZiPzaxNtZnLNj2mA54YQ== +Prime1: z08i0sCcEpr4MZi4TReohPWp3F5vMQYVux8B3ltmJ3kKraXEmVEVmujhWa+ZDxhJmwKoba65vNEsUbSJN6WwJd7PVyskHb2GnWGK8NtlainFEuiS5CDxwULR4o2SI+Pij9thMQoA13ZTKc9s3E57VgcvJ7vaoD/1ZtpP7tdaerE= +Prime2: yMid465M6bCXXUfWg7oq6A4MZUULbEPKvs+qGIersdiHfrFRGJ0Lviujs8KHaPS5rt4YmbpQU9tGbJBauY17T03qr/mQOBDx5gDkAJcJ0EUHudFslwqyn50THlJsKrFOxBYl7laY0v6CGCMyuZok8qyhiPHv5dhzSc9zwKaXZ1E= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample-e.+008+53973.key b/tests/dns/comparekeys/Kexample-e.+008+53973.key new file mode 100644 index 0000000..a4b0d03 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-e.+008+53973.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 53973, for example-e. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example-e. IN DNSKEY 256 3 8 BQEAAAABophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2Z V7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ 4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+ m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7k VDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+ oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN 1ik92pzkr2UJAQ== diff --git a/tests/dns/comparekeys/Kexample-e.+008+53973.private b/tests/dns/comparekeys/Kexample-e.+008+53973.private new file mode 100644 index 0000000..765ca1a --- /dev/null +++ b/tests/dns/comparekeys/Kexample-e.+008+53973.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: ophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2ZV7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7kVDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN1ik92pzkr2UJAQ== +PublicExponent: AQAAAAE= +PrivateExponent: lFgeQHf3klxXlfkNmczDEYHXl37i2iCgZdUsqtho/3LFdfWZrxZr6ACM040dKLHiw1UdhODy5h/Zstif4Ww3LsKKBgpbMnZUTMOI9R+eQmRrhCI96XAur5AIuJCHa+jIbCiamh8xY6g0byp/sUHQxYV02I/lcTdQSeGHSOSqX3QjB835OVa18hyW6txAxM4DVGo/NvIJw2ItSl2qwHTMDHK45t4YbnKEd6suriUiveyax5dU1JtpviwHJiAFPy+L68jMo8cfr+JCLWW2OJYkrBXb8kwqaPsV0RCGZ59sePyRdSYRgNi1brBStesctVc5UfSxH6p2A6C28LdrubcXAQ== +Prime1: z08i0sCcEpr4MZi4TReohPWp3F5vMQYVux8B3ltmJ3kKraXEmVEVmujhWa+ZDxhJmwKoba65vNEsUbSJN6WwJd7PVyskHb2GnWGK8NtlainFEuiS5CDxwULR4o2SI+Pij9thMQoA13ZTKc9s3E57VgcvJ7vaoD/1ZtpP7tdaerE= +Prime2: yMid465M6bCXXUfWg7oq6A4MZUULbEPKvs+qGIersdiHfrFRGJ0Lviujs8KHaPS5rt4YmbpQU9tGbJBauY17T03qr/mQOBDx5gDkAJcJ0EUHudFslwqyn50THlJsKrFOxBYl7laY0v6CGCMyuZok8qyhiPHv5dhzSc9zwKaXZ1E= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample-n.+008+37464.key b/tests/dns/comparekeys/Kexample-n.+008+37464.key new file mode 100644 index 0000000..da2e16a --- /dev/null +++ b/tests/dns/comparekeys/Kexample-n.+008+37464.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 37464, for example-n. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example-n. IN DNSKEY 256 3 8 AwEAAbxHOF8G0xw9ekCodhL8KivuZ3o0jmGlycLiXBjBN8c5R5fjLjUh D0gy3IDbDC+kLaPhHGF/MwrSEjrgSowxZ8nrxDzsq5ZdpeUsYaNrbQEY /mqf35T/9/Ulm4v06x58v/NTugWd05Xq04aAyfm7EViyGFzmVOVfPnll h9xQtvWEWoRWPseFw+dY5/nc/+xB/IsQMihoH2rO+cek/lsP3R9DsHCG RbQ/ks/+rrp6/O+QJZyZrzsONl7mlMDXNy3Pz9J4qMW2W6Mz702LN324 7/9UsetDGGbuZfrCLMpKWXzdsJm36DOk4aMooS9111plfXaXQgQNcL5G 021utpTau+8= diff --git a/tests/dns/comparekeys/Kexample-n.+008+37464.private b/tests/dns/comparekeys/Kexample-n.+008+37464.private new file mode 100644 index 0000000..65689a2 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-n.+008+37464.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: vEc4XwbTHD16QKh2EvwqK+5nejSOYaXJwuJcGME3xzlHl+MuNSEPSDLcgNsML6Qto+EcYX8zCtISOuBKjDFnyevEPOyrll2l5Sxho2ttARj+ap/flP/39SWbi/TrHny/81O6BZ3TlerThoDJ+bsRWLIYXOZU5V8+eWWH3FC29YRahFY+x4XD51jn+dz/7EH8ixAyKGgfas75x6T+Ww/dH0OwcIZFtD+Sz/6uunr875AlnJmvOw42XuaUwNc3Lc/P0nioxbZbozPvTYs3fbjv/1Sx60MYZu5l+sIsykpZfN2wmbfoM6ThoyihL3XXWmV9dpdCBA1wvkbTbW62lNq77w== +PublicExponent: AQAB +PrivateExponent: lFgeQHf3klxXlfkNmczDEYHXl37i2iCgZdUsqtho/3LFdfWZrxZr6ACM040dKLHiw1UdhODy5h/Zstif4Ww3LsKKBgpbMnZUTMOI9R+eQmRrhCI96XAur5AIuJCHa+jIbCiamh8xY6g0byp/sUHQxYV02I/lcTdQSeGHSOSqX3QjB835OVa18hyW6txAxM4DVGo/NvIJw2ItSl2qwHTMDHK45t4YbnKEd6suriUiveyax5dU1JtpviwHJiAFPy+L68jMo8cfr+JCLWW2OJYkrBXb8kwqaPsV0RCGZ59sePyRdSYRgNi1brBStesctVc5UfSxH6p2A6C28LdrubcXAQ== +Prime1: z08i0sCcEpr4MZi4TReohPWp3F5vMQYVux8B3ltmJ3kKraXEmVEVmujhWa+ZDxhJmwKoba65vNEsUbSJN6WwJd7PVyskHb2GnWGK8NtlainFEuiS5CDxwULR4o2SI+Pij9thMQoA13ZTKc9s3E57VgcvJ7vaoD/1ZtpP7tdaerE= +Prime2: yMid465M6bCXXUfWg7oq6A4MZUULbEPKvs+qGIersdiHfrFRGJ0Lviujs8KHaPS5rt4YmbpQU9tGbJBauY17T03qr/mQOBDx5gDkAJcJ0EUHudFslwqyn50THlJsKrFOxBYl7laY0v6CGCMyuZok8qyhiPHv5dhzSc9zwKaXZ1E= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample-p.+008+53461.key b/tests/dns/comparekeys/Kexample-p.+008+53461.key new file mode 100644 index 0000000..20ffcfd --- /dev/null +++ b/tests/dns/comparekeys/Kexample-p.+008+53461.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 53461, for example-p. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example-p. IN DNSKEY 256 3 8 AwEAAaKYSOPDzZvfue5sU71xPCJKJpB5kZGl4vTp3OI8W+nN1YFtmVe2 2gM666AEutDAEB7cLkyoKCOH0+4Lh1ucPr6OmdWkHfk7uZv58eH0kOAV tNz2xhEF/YHSD7cnBEU9g0knGwpWuzSJKRhGhNoaVus9g1MaAn8efptz HIduIwgAeXV3BDCUpY6HbpwjDxOGCzCUYDRgcex37kYuCyW0PvlO5FQ0 DT0LpjcgBmIBpXol7sYpmKdOKJrm4x2lwGntr4K+bCdNYI2PRPJjPqAf jlvIvJylGUaqFJasw7PSMQIkgcQ4OQXVrhE8uGLdYvP1cusLuROIjdYp Pdqc5K9lCQE= diff --git a/tests/dns/comparekeys/Kexample-p.+008+53461.private b/tests/dns/comparekeys/Kexample-p.+008+53461.private new file mode 100644 index 0000000..063c925 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-p.+008+53461.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: ophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2ZV7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7kVDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN1ik92pzkr2UJAQ== +PublicExponent: AQAB +PrivateExponent: lFgeQHf3klxXlfkNmczDEYHXl37i2iCgZdUsqtho/3LFdfWZrxZr6ACM040dKLHiw1UdhODy5h/Zstif4Ww3LsKKBgpbMnZUTMOI9R+eQmRrhCI96XAur5AIuJCHa+jIbCiamh8xY6g0byp/sUHQxYV02I/lcTdQSeGHSOSqX3QjB835OVa18hyW6txAxM4DVGo/NvIJw2ItSl2qwHTMDHK45t4YbnKEd6suriUiveyax5dU1JtpviwHJiAFPy+L68jMo8cfr+JCLWW2OJYkrBXb8kwqaPsV0RCGZ59sePyRdSYRgNi1brBStesctVc5UfSxH6p2A6C28LdrubcXAQ== +Prime1: 5YpfVjEtL1owW9gSFbIMx65POr+fiktxirgy1bc5fSsVqUgG6zhbaN/VpWcNZG0Zg5xd6S7C8V3djGlnJN8wZIyjIh7+Z3WWjqbOD9oY7rC1fR+W0OvbCmZiEzOpRJ5qoMOh1MzkkanhMy0/ICpaa8eQ9zEb80oTIQpFgoLn7K0= +Prime2: yMid465M6bCXXUfWg7oq6A4MZUULbEPKvs+qGIersdiHfrFRGJ0Lviujs8KHaPS5rt4YmbpQU9tGbJBauY17T03qr/mQOBDx5gDkAJcJ0EUHudFslwqyn50THlJsKrFOxBYl7laY0v6CGCMyuZok8qyhiPHv5dhzSc9zwKaXZ1E= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample-private.+002+65316.key b/tests/dns/comparekeys/Kexample-private.+002+65316.key new file mode 100644 index 0000000..7cc002d --- /dev/null +++ b/tests/dns/comparekeys/Kexample-private.+002+65316.key @@ -0,0 +1 @@ +example-private. IN KEY 512 3 2 AAECAAAAgKVXnUOFKMvLvwO/VdY9bq+eOPBxrRWsDpcL9FJ9+hklVvii pcLOIhiKLeHI/u9vM2nhd8+opIW92+j2pB185MRgSrINQcC+XpI/xiDG HwE78bQ+2Ykb/memG+ctkVyrFGHtaJLCUGWrUHy1jbtvYeaKeS92jR/2 4oryt3N851u5 diff --git a/tests/dns/comparekeys/Kexample-private.+002+65316.private b/tests/dns/comparekeys/Kexample-private.+002+65316.private new file mode 100644 index 0000000..1f00fa9 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-private.+002+65316.private @@ -0,0 +1,9 @@ +Private-key-format: v1.3 +Algorithm: 2 (DH) +Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5lOB//////////8= +Generator(g): Ag== +Private_value(x): dLr0sfk/P1V0DfQ7Ke3IIaSM8nHjtrBRlMcQXRMVrLhbbKeCodvpSRtI0Nwtt38Df8dbGGtP676my2Ht2UHyL7rO0+ASv98NCysL0Xp6q2a7fn67iGFUBTg3jzXC89FYv4sYNeVLDGrKC3EjtGkalzgDVuzEC8CqRkWKeys3ufc= +Public_value(y): pVedQ4Uoy8u/A79V1j1ur5448HGtFawOlwv0Un36GSVW+KKlws4iGIot4cj+728zaeF3z6ikhb3b6PakHXzkxGBKsg1BwL5ekj/GIMYfATvxtD7ZiRv+Z6Yb5y2RXKsUYe1oksJQZatQfLWNu29h5op5L3aNH/biivK3c3znW7k= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample-q.+008+53461.key b/tests/dns/comparekeys/Kexample-q.+008+53461.key new file mode 100644 index 0000000..5d4a0e7 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-q.+008+53461.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 53461, for example-q. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example-q. IN DNSKEY 256 3 8 AwEAAaKYSOPDzZvfue5sU71xPCJKJpB5kZGl4vTp3OI8W+nN1YFtmVe2 2gM666AEutDAEB7cLkyoKCOH0+4Lh1ucPr6OmdWkHfk7uZv58eH0kOAV tNz2xhEF/YHSD7cnBEU9g0knGwpWuzSJKRhGhNoaVus9g1MaAn8efptz HIduIwgAeXV3BDCUpY6HbpwjDxOGCzCUYDRgcex37kYuCyW0PvlO5FQ0 DT0LpjcgBmIBpXol7sYpmKdOKJrm4x2lwGntr4K+bCdNYI2PRPJjPqAf jlvIvJylGUaqFJasw7PSMQIkgcQ4OQXVrhE8uGLdYvP1cusLuROIjdYp Pdqc5K9lCQE= diff --git a/tests/dns/comparekeys/Kexample-q.+008+53461.private b/tests/dns/comparekeys/Kexample-q.+008+53461.private new file mode 100644 index 0000000..6b2e563 --- /dev/null +++ b/tests/dns/comparekeys/Kexample-q.+008+53461.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: ophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2ZV7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7kVDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN1ik92pzkr2UJAQ== +PublicExponent: AQAB +PrivateExponent: lFgeQHf3klxXlfkNmczDEYHXl37i2iCgZdUsqtho/3LFdfWZrxZr6ACM040dKLHiw1UdhODy5h/Zstif4Ww3LsKKBgpbMnZUTMOI9R+eQmRrhCI96XAur5AIuJCHa+jIbCiamh8xY6g0byp/sUHQxYV02I/lcTdQSeGHSOSqX3QjB835OVa18hyW6txAxM4DVGo/NvIJw2ItSl2qwHTMDHK45t4YbnKEd6suriUiveyax5dU1JtpviwHJiAFPy+L68jMo8cfr+JCLWW2OJYkrBXb8kwqaPsV0RCGZ59sePyRdSYRgNi1brBStesctVc5UfSxH6p2A6C28LdrubcXAQ== +Prime1: z08i0sCcEpr4MZi4TReohPWp3F5vMQYVux8B3ltmJ3kKraXEmVEVmujhWa+ZDxhJmwKoba65vNEsUbSJN6WwJd7PVyskHb2GnWGK8NtlainFEuiS5CDxwULR4o2SI+Pij9thMQoA13ZTKc9s3E57VgcvJ7vaoD/1ZtpP7tdaerE= +Prime2: 0fs3ncL5/2qzq2dmPXLYcOfc1EGSuESO0VpREP8EpTkyPKeVw5LaF9TgZRqPWlRf2T0LPoZ766xLAn090u0pLQ5fWM96NMas7kS+rxtRssat6MiQo3YfoU3ysk3xuPzrMBHyn/N42CjSG+bJEToHR7V16KsCT6dBIPkI3tj/Yos= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample.+002+65316.key b/tests/dns/comparekeys/Kexample.+002+65316.key new file mode 100644 index 0000000..c2f4703 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+002+65316.key @@ -0,0 +1 @@ +example. IN KEY 512 3 2 AAECAAAAgKVXnUOFKMvLvwO/VdY9bq+eOPBxrRWsDpcL9FJ9+hklVvii pcLOIhiKLeHI/u9vM2nhd8+opIW92+j2pB185MRgSrINQcC+XpI/xiDG HwE78bQ+2Ykb/memG+ctkVyrFGHtaJLCUGWrUHy1jbtvYeaKeS92jR/2 4oryt3N851u5 diff --git a/tests/dns/comparekeys/Kexample.+002+65316.private b/tests/dns/comparekeys/Kexample.+002+65316.private new file mode 100644 index 0000000..e872834 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+002+65316.private @@ -0,0 +1,9 @@ +Private-key-format: v1.3 +Algorithm: 2 (DH) +Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5lOB//////////8= +Generator(g): Ag== +Private_value(x): bUMVaaSCAPT0NK7AkIa0JA1SSw83x8WxS+iePECQwr4xDDMnevNHWK1nIofUM2qNbpDe2KvFIt9tu+1UgZgOTLoQFipePtHKOjoRX6XsGNzKmL8WZOlw/QJw0D5RIn7l7tvmBCeNHINl9IWVgMLTi+wgzrJxSeGe406q23Jn4Uc= +Public_value(y): pVedQ4Uoy8u/A79V1j1ur5448HGtFawOlwv0Un36GSVW+KKlws4iGIot4cj+728zaeF3z6ikhb3b6PakHXzkxGBKsg1BwL5ekj/GIMYfATvxtD7ZiRv+Z6Yb5y2RXKsUYe1oksJQZatQfLWNu29h5op5L3aNH/biivK3c3znW7k= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample.+008+53461.key b/tests/dns/comparekeys/Kexample.+008+53461.key new file mode 100644 index 0000000..33c8188 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+008+53461.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 53461, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 256 3 8 AwEAAaKYSOPDzZvfue5sU71xPCJKJpB5kZGl4vTp3OI8W+nN1YFtmVe2 2gM666AEutDAEB7cLkyoKCOH0+4Lh1ucPr6OmdWkHfk7uZv58eH0kOAV tNz2xhEF/YHSD7cnBEU9g0knGwpWuzSJKRhGhNoaVus9g1MaAn8efptz HIduIwgAeXV3BDCUpY6HbpwjDxOGCzCUYDRgcex37kYuCyW0PvlO5FQ0 DT0LpjcgBmIBpXol7sYpmKdOKJrm4x2lwGntr4K+bCdNYI2PRPJjPqAf jlvIvJylGUaqFJasw7PSMQIkgcQ4OQXVrhE8uGLdYvP1cusLuROIjdYp Pdqc5K9lCQE= diff --git a/tests/dns/comparekeys/Kexample.+008+53461.private b/tests/dns/comparekeys/Kexample.+008+53461.private new file mode 100644 index 0000000..dd4d9a4 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+008+53461.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: ophI48PNm9+57mxTvXE8IkomkHmRkaXi9Onc4jxb6c3VgW2ZV7baAzrroAS60MAQHtwuTKgoI4fT7guHW5w+vo6Z1aQd+Tu5m/nx4fSQ4BW03PbGEQX9gdIPtycERT2DSScbCla7NIkpGEaE2hpW6z2DUxoCfx5+m3Mch24jCAB5dXcEMJSljodunCMPE4YLMJRgNGBx7HfuRi4LJbQ++U7kVDQNPQumNyAGYgGleiXuximYp04omubjHaXAae2vgr5sJ01gjY9E8mM+oB+OW8i8nKUZRqoUlqzDs9IxAiSBxDg5BdWuETy4Yt1i8/Vy6wu5E4iN1ik92pzkr2UJAQ== +PublicExponent: AQAB +PrivateExponent: lFgeQHf3klxXlfkNmczDEYHXl37i2iCgZdUsqtho/3LFdfWZrxZr6ACM040dKLHiw1UdhODy5h/Zstif4Ww3LsKKBgpbMnZUTMOI9R+eQmRrhCI96XAur5AIuJCHa+jIbCiamh8xY6g0byp/sUHQxYV02I/lcTdQSeGHSOSqX3QjB835OVa18hyW6txAxM4DVGo/NvIJw2ItSl2qwHTMDHK45t4YbnKEd6suriUiveyax5dU1JtpviwHJiAFPy+L68jMo8cfr+JCLWW2OJYkrBXb8kwqaPsV0RCGZ59sePyRdSYRgNi1brBStesctVc5UfSxH6p2A6C28LdrubcXAQ== +Prime1: z08i0sCcEpr4MZi4TReohPWp3F5vMQYVux8B3ltmJ3kKraXEmVEVmujhWa+ZDxhJmwKoba65vNEsUbSJN6WwJd7PVyskHb2GnWGK8NtlainFEuiS5CDxwULR4o2SI+Pij9thMQoA13ZTKc9s3E57VgcvJ7vaoD/1ZtpP7tdaerE= +Prime2: yMid465M6bCXXUfWg7oq6A4MZUULbEPKvs+qGIersdiHfrFRGJ0Lviujs8KHaPS5rt4YmbpQU9tGbJBauY17T03qr/mQOBDx5gDkAJcJ0EUHudFslwqyn50THlJsKrFOxBYl7laY0v6CGCMyuZok8qyhiPHv5dhzSc9zwKaXZ1E= +Exponent1: iresWJOzm6uAukczw7o59EYiFChIhOhKcDyOVoiYMX+ICqvqgqDEMTT1XbrnUzdwQT4lD8ej11msKzv/uXGwDZcq7GwcrZ3dTsAvZX2ZPdGXYlCnwejde/FHWi5bBJL/Tj2AqnzEFWjCuy5l7IDDfMwv3ImSADrr7ZfVdr85dvE= +Exponent2: aULzs4ePfvw7foXI6mpRUDL9QKI/6NRpmDtam12VH7m63yqqr1K1808BlZ4oS1fxeMGq9/z7W9sbQpMzXQ/VU7Avl24os5v+lWxmHAES/gMSl9I5Mb5EAvXgLgdb+c3W02ohHKB9ojAXl/vr/e3X7Pmf/iGIeWFOn6WIs7kiquE= +Coefficient: HS4bN41s6Ak9+6m3vhmLzgHtWMavnLpDkmd6wTBttbtKXHfjbvxMUt4RYeF8BXRtfIqIOZqJJngais1wQfOsgVhHrKVwX+MOThyOk4SD+pvnG6g1B+qUS1czPGP7Rf+7668wK8ZxV9w0+YDbTJgPgivD0lBnLXwT+KCLprMXTe4= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample.+013+19786.key b/tests/dns/comparekeys/Kexample.+013+19786.key new file mode 100644 index 0000000..ccfcc97 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+013+19786.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 19786, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 256 3 13 S35Z1XtGlnnU7BBahMJwAZXXff+JupyIDssNfJyrugLKq5R10TJ5tU3W r3VuP6aJNs6+uL2cMPVTVT1vr1Aqwg== diff --git a/tests/dns/comparekeys/Kexample.+013+19786.private b/tests/dns/comparekeys/Kexample.+013+19786.private new file mode 100644 index 0000000..0d72cf1 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+013+19786.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: ZYcYhR5f98vI1+BFGKLIrarZrqxJM4mRy9tvwntdYoo= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample.+015+63663.key b/tests/dns/comparekeys/Kexample.+015+63663.key new file mode 100644 index 0000000..92db9fb --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+015+63663.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 63663, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 256 3 15 ZLlkI5q8XDkP3D7Zxdbmuqh4yp90mbvdcNT0xSGLDtI= diff --git a/tests/dns/comparekeys/Kexample.+015+63663.private b/tests/dns/comparekeys/Kexample.+015+63663.private new file mode 100644 index 0000000..c2c48f3 --- /dev/null +++ b/tests/dns/comparekeys/Kexample.+015+63663.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 15 (ED25519) +PrivateKey: rGYsnf8nPlg7kg7qRcIXYShPsTiMHTeWJInNrW9GwSQ= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample2.+002+19823.key b/tests/dns/comparekeys/Kexample2.+002+19823.key new file mode 100644 index 0000000..9d521f7 --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+002+19823.key @@ -0,0 +1 @@ +example2. IN KEY 512 3 2 AAECAAAAgCxVfxiyTe8C83ou8KXSu9WmzGwCYWB2NkdS87Kz0PgTuBay JkDDAEeR6CIYClA6PXBp2GXUPHoYWag9zVOVU85PYu0KRZF69EN0IVsA OCtgikOcr5yD4esSMwTTPk/OQ8qW/yGf1DvdpXuiu3P/wSpzVGL8tHFQ 2XURydYytol0 diff --git a/tests/dns/comparekeys/Kexample2.+002+19823.private b/tests/dns/comparekeys/Kexample2.+002+19823.private new file mode 100644 index 0000000..f6722f6 --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+002+19823.private @@ -0,0 +1,9 @@ +Private-key-format: v1.3 +Algorithm: 2 (DH) +Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5lOB//////////8= +Generator(g): Ag== +Private_value(x): W0EpuIMltmMuZAKcCmRe/Ix9WsHPU/GLfqbjHKCjgYdRFzwqHyVp6z+uf8EgmHBD1bbBjwfcnRse8xfqqmt/wZIRdDzjRq/oZdKtJHqFZSO+MQZ5DKrdojKU7UEl/j44heJzVO0qFkrPvWglRt+780LP0awkfetecXDxvJT+HIw= +Public_value(y): LFV/GLJN7wLzei7wpdK71abMbAJhYHY2R1LzsrPQ+BO4FrImQMMAR5HoIhgKUDo9cGnYZdQ8ehhZqD3NU5VTzk9i7QpFkXr0Q3QhWwA4K2CKQ5yvnIPh6xIzBNM+T85Dypb/IZ/UO92le6K7c//BKnNUYvy0cVDZdRHJ1jK2iXQ= +Created: 20211027221355 +Publish: 20211027221355 +Activate: 20211027221355 diff --git a/tests/dns/comparekeys/Kexample2.+008+37993.key b/tests/dns/comparekeys/Kexample2.+008+37993.key new file mode 100644 index 0000000..c0e09a1 --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+008+37993.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 37993, for example2. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example2. IN DNSKEY 256 3 8 AwEAAaSRhPf0XhYR52Kpi0RZJgEnpidvuz2Ywdyh8k5CKwal9nM15PNc 4ZoPEVGO+ize53hq0iUkVlBhAfhQE31Fhf4zU544fezBEaz33hiajEzL ZITux9N83WfoYSNnyufvSGzNcpNM6LHKdDwMr1kr9tTgNeuiTAlPv5z9 BNtfv2B25moVm1DoxMCd8WH0jYC452a2lGM+Fbd45o02OO7V8balPwJh MM2bbeWg5G+tbvCAot93KxtavyOMKV4siv3ZH639J0dIb10L8nNrN0Ge UjkX8yU3fgeWB4Oldtzx0SHxG75NWjRLnpVzBq5GeacLc4RsN+S+nhYW 4Wv2A066w70= diff --git a/tests/dns/comparekeys/Kexample2.+008+37993.private b/tests/dns/comparekeys/Kexample2.+008+37993.private new file mode 100644 index 0000000..887ad2b --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+008+37993.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: pJGE9/ReFhHnYqmLRFkmASemJ2+7PZjB3KHyTkIrBqX2czXk81zhmg8RUY76LN7neGrSJSRWUGEB+FATfUWF/jNTnjh97MERrPfeGJqMTMtkhO7H03zdZ+hhI2fK5+9IbM1yk0zoscp0PAyvWSv21OA166JMCU+/nP0E21+/YHbmahWbUOjEwJ3xYfSNgLjnZraUYz4Vt3jmjTY47tXxtqU/AmEwzZtt5aDkb61u8ICi33crG1q/I4wpXiyK/dkfrf0nR0hvXQvyc2s3QZ5SORfzJTd+B5YHg6V23PHRIfEbvk1aNEuelXMGrkZ5pwtzhGw35L6eFhbha/YDTrrDvQ== +PublicExponent: AQAB +PrivateExponent: O/HFvYwFuYRMBGQ9lmfisAkBPNw2F/nMo9FZsafohENvwgefngX3J2bVqB+sgSuwpOxEH8NcrWqojQqeDsOES1Pm4XsyY0rwZVDkVZH2CQMNWl6f6ylQfMjomTz1bAZ9GyS612zsVdapADaeqJybDG+fNHWpvLqP0V9YpY/65efTvrA3Qu+XpDvLaJ34yjkeEGUgysNP3KkDTeJTY/ksKi6ODtdzbKpufjZS8b6BL97XcFcNGiwu/gNPCvtmm/H+tXaNYyijG7bNGPOpHFhlMCT13o8XLrR/OGty6VY6PpjaEnvlZUZnWHUwn/JmNoZRJoXAAEerk3nS+tOhRmcrAQ== +Prime1: 2W8JHYaTn7XefxxwaDZWFrVtHnnd0vUZvBBNA1PJeRfDr+yPxyWcgYx1OBxKkJsYGiob0i992W2HXuz2KS81yBCtH/uLK1Y+mkjgme4MWZupZ0RsKA1TkgIrJs174Dv3P/yqc+/R4eiwUGt10493MS1PJFF0CmisDzgjai/JLIM= +Prime2: wcIKikgzOsq2A2Hl7qPCeA3oKTc66eFVNvB/KH91/hNFKNm0kAvhHrNe9rSoU+JywCNbX/Fs7X6SuHHJaRs+KpSBadnqfwEIngCq2Y00nT3sbETx4VNbXFD6MPPo3MWDi61/TCyrtBujutavo5ghj2oVzNGqMT3UyhaVNrJp2r8= +Exponent1: GsEO3hMxFvXJ6toU+r202hZ41scoBE0kXX+j+kTVBZFnAr6Y8mguWcJuqfjRM/nhfVaxFavCUH6pqYR+xZKJi5SBuO26shpqmZFeEZK48k21Cn/gzwzUu6KIrL2cAHtgcP8l+h4INUPsbfjLBr0gbWyl0FI1dRJsGXNO6EH4/wE= +Exponent2: WrgcsUQ+4E8bS5ghzUtVeVqhkfKvHeSIPpH6J58OQukI36iXNz6op/Q6CW7qxWPocHfdh52Fb+lsjvmP4SuFPvCLa2FBvzdfroMHe5b2xIzCzqq1Sdf6lc3AZv080WmVPuf8C1F7D3hFf+yXDhTj2b9E98JPWoDlyb0rHhIJKAc= +Coefficient: aVDpGheH0UJ8aWPRIRHyjMTCIPB8zmhfwugpV11Z/OXNb2uaNRcnVKujs1mlSydoIfFQSuFf3iPs7ytaJUfcQJ+k1QAtssJC1HXF14t0p5o99QxuQLgmNtPHD7m2aeAyFJoycF24UmDnFmOPSNm1fnJs9LrBPFZFdTBGhl8plEo= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample2.+013+16384.key b/tests/dns/comparekeys/Kexample2.+013+16384.key new file mode 100644 index 0000000..b6351ad --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+013+16384.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 16384, for example2. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example2. IN DNSKEY 256 3 13 p+ohRFVh6wmdAhbU/cF2FYoE/i49FxnvKwif0Co0D7RhBui4AMFOsFYu 9AIqEBaCGurjGYl7WDYRrjRMRjWW1g== diff --git a/tests/dns/comparekeys/Kexample2.+013+16384.private b/tests/dns/comparekeys/Kexample2.+013+16384.private new file mode 100644 index 0000000..74a371c --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+013+16384.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: ZNsU73iCEeC837TA59nT/QDtd3oYsrYDWy8jfazZQkA= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample2.+015+37529.key b/tests/dns/comparekeys/Kexample2.+015+37529.key new file mode 100644 index 0000000..9a8cf77 --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+015+37529.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 37529, for example2. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example2. IN DNSKEY 256 3 15 zyiLjDymEPN90rwi/y0mWXLnUm0Nq7T9Kc8VoubF2Io= diff --git a/tests/dns/comparekeys/Kexample2.+015+37529.private b/tests/dns/comparekeys/Kexample2.+015+37529.private new file mode 100644 index 0000000..aa70804 --- /dev/null +++ b/tests/dns/comparekeys/Kexample2.+015+37529.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 15 (ED25519) +PrivateKey: pUR2VLqbi4XtBNImbVDRHrjugMMmaXmy6noV0/jy/rA= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/comparekeys/Kexample3.+002+17187.key b/tests/dns/comparekeys/Kexample3.+002+17187.key new file mode 100644 index 0000000..0260293 --- /dev/null +++ b/tests/dns/comparekeys/Kexample3.+002+17187.key @@ -0,0 +1 @@ +example3. IN KEY 512 3 2 AIDzVP5SeKpxZmlbok6AbdFT5aCVAg3AnQln24CKoc0IXRyTdnhmIEWw VatzRrUY0V6SSwwe3740yk46/TdSvVmZkakw52yn3M661ra5L8kouAK4 rpyM6uulsS0dyjyRzomHJg2zwOukzHBVINFheKsJ25MvdPpp9E64IVji jp/x3wABBQCAFb1Je3cKpt/4gS+KRx9hxFOF5c64ytC9tf0hp2hP4OiP YCu8o5C3qh+PexZAx58m6cSaFlzf3DZ3GGsvamDj5H8YpvP4FeRVva9V jH4VeU4/VtbdNweDUHwAguGJ77MXw+bruHhpbsFVSxHrnNg99WHghaRy YzfFzphJHKBxACo= diff --git a/tests/dns/comparekeys/Kexample3.+002+17187.private b/tests/dns/comparekeys/Kexample3.+002+17187.private new file mode 100644 index 0000000..47ef4bc --- /dev/null +++ b/tests/dns/comparekeys/Kexample3.+002+17187.private @@ -0,0 +1,9 @@ +Private-key-format: v1.3 +Algorithm: 2 (DH) +Prime(p): 81T+UniqcWZpW6JOgG3RU+WglQINwJ0JZ9uAiqHNCF0ck3Z4ZiBFsFWrc0a1GNFekksMHt++NMpOOv03Ur1ZmZGpMOdsp9zOuta2uS/JKLgCuK6cjOrrpbEtHco8kc6JhyYNs8DrpMxwVSDRYXirCduTL3T6afROuCFY4o6f8d8= +Generator(g): BQ== +Private_value(x): ccA7JRCvjAE1ASWTtObkvO5k58oKdJ+bzcd/H3cOQsPAhItUc8Pfca2ILWYzDfs+nl+WKLfODQ9cRUabp4SUh0GKPnqJVM1UgDXwme/98NEtVFhs2VawT40wHLkcdPN9jACH11l28u1qsDVb7MRj2UXGC/oszRwQ7s3rN1UlHO8= +Public_value(y): Fb1Je3cKpt/4gS+KRx9hxFOF5c64ytC9tf0hp2hP4OiPYCu8o5C3qh+PexZAx58m6cSaFlzf3DZ3GGsvamDj5H8YpvP4FeRVva9VjH4VeU4/VtbdNweDUHwAguGJ77MXw+bruHhpbsFVSxHrnNg99WHghaRyYzfFzphJHKBxACo= +Created: 20211027221447 +Publish: 20211027221447 +Activate: 20211027221447 diff --git a/tests/dns/db_test.c b/tests/dns/db_test.c new file mode 100644 index 0000000..787ac85 --- /dev/null +++ b/tests/dns/db_test.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/journal.h> +#include <dns/name.h> +#include <dns/rdatalist.h> + +#include <tests/dns.h> + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +/* + * Individual unit tests + */ + +/* test multiple calls to dns_db_getoriginnode */ +ISC_RUN_TEST_IMPL(getoriginnode) { + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + isc_result_t result; + + UNUSED(state); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_getoriginnode(db, &node); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + + result = dns_db_getoriginnode(db, &node); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + + dns_db_detach(&db); +} + +/* test getservestalettl and setservestalettl */ +ISC_RUN_TEST_IMPL(getsetservestalettl) { + dns_db_t *db = NULL; + isc_result_t result; + dns_ttl_t ttl; + + UNUSED(state); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + ttl = 5000; + result = dns_db_getservestalettl(db, &ttl); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(ttl, 0); + + ttl = 6 * 3600; + result = dns_db_setservestalettl(db, ttl); + assert_int_equal(result, ISC_R_SUCCESS); + + ttl = 5000; + result = dns_db_getservestalettl(db, &ttl); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(ttl, 6 * 3600); + + dns_db_detach(&db); +} + +/* check DNS_DBFIND_STALEOK works */ +ISC_RUN_TEST_IMPL(dns_dbfind_staleok) { + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_fixedname_t example_fixed; + dns_fixedname_t found_fixed; + dns_name_t *example; + dns_name_t *found; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + int count; + int pass; + isc_result_t result; + unsigned char data[] = { 0x0a, 0x00, 0x00, 0x01 }; + + UNUSED(state); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + example = dns_fixedname_initname(&example_fixed); + found = dns_fixedname_initname(&found_fixed); + + result = dns_name_fromstring(example, "example", 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Pass 0: default; no stale processing permitted. + * Pass 1: stale processing for 1 second. + * Pass 2: stale turned off after being on. + */ + for (pass = 0; pass < 3; pass++) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + /* 10.0.0.1 */ + rdata.data = data; + rdata.length = 4; + rdata.rdclass = dns_rdataclass_in; + rdata.type = dns_rdatatype_a; + + dns_rdatalist_init(&rdatalist); + rdatalist.ttl = 2; + rdatalist.type = dns_rdatatype_a; + rdatalist.rdclass = dns_rdataclass_in; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + switch (pass) { + case 0: + /* default: stale processing off */ + break; + case 1: + /* turn on stale processing */ + result = dns_db_setservestalettl(db, 1); + assert_int_equal(result, ISC_R_SUCCESS); + break; + case 2: + /* turn off stale processing */ + result = dns_db_setservestalettl(db, 0); + assert_int_equal(result, ISC_R_SUCCESS); + break; + } + + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_findnode(db, example, true, &node); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_addrdataset(db, node, NULL, 0, &rdataset, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_db_detachnode(db, &node); + dns_rdataset_disassociate(&rdataset); + + result = dns_db_find(db, example, NULL, dns_rdatatype_a, 0, 0, + &node, found, &rdataset, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * May loop for up to 2 seconds performing non stale lookups. + */ + count = 0; + do { + count++; + assert_in_range(count, 1, 21); /* loop sanity */ + assert_int_equal(rdataset.attributes & + DNS_RDATASETATTR_STALE, + 0); + assert_true(rdataset.ttl > 0); + dns_db_detachnode(db, &node); + dns_rdataset_disassociate(&rdataset); + + usleep(100000); /* 100 ms */ + + result = dns_db_find(db, example, NULL, dns_rdatatype_a, + 0, 0, &node, found, &rdataset, + NULL); + } while (result == ISC_R_SUCCESS); + + assert_int_equal(result, ISC_R_NOTFOUND); + + /* + * Check whether we can get stale data. + */ + result = dns_db_find(db, example, NULL, dns_rdatatype_a, + DNS_DBFIND_STALEOK, 0, &node, found, + &rdataset, NULL); + switch (pass) { + case 0: + assert_int_equal(result, ISC_R_NOTFOUND); + break; + case 1: + /* + * Should loop for 1 second with stale lookups then + * stop. + */ + count = 0; + do { + count++; + assert_in_range(count, 0, 49); /* loop sanity */ + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdataset.attributes & + DNS_RDATASETATTR_STALE, + DNS_RDATASETATTR_STALE); + dns_db_detachnode(db, &node); + dns_rdataset_disassociate(&rdataset); + + usleep(100000); /* 100 ms */ + + result = dns_db_find( + db, example, NULL, dns_rdatatype_a, + DNS_DBFIND_STALEOK, 0, &node, found, + &rdataset, NULL); + } while (result == ISC_R_SUCCESS); + /* + * usleep(100000) can be slightly less than 10ms so + * allow the count to reach 11. + */ + assert_in_range(count, 1, 11); + assert_int_equal(result, ISC_R_NOTFOUND); + break; + case 2: + assert_int_equal(result, ISC_R_NOTFOUND); + break; + } + } + + dns_db_detach(&db); +} + +/* database class */ +ISC_RUN_TEST_IMPL(class) { + isc_result_t result; + dns_db_t *db = NULL; + + UNUSED(state); + + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db", + dns_masterformat_text, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_int_equal(dns_db_class(db), dns_rdataclass_in); + + dns_db_detach(&db); +} + +/* database type */ +ISC_RUN_TEST_IMPL(dbtype) { + isc_result_t result; + dns_db_t *db = NULL; + + UNUSED(state); + + /* DB has zone semantics */ + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db", + dns_masterformat_text, 0); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(dns_db_iszone(db)); + assert_false(dns_db_iscache(db)); + dns_db_detach(&db); + + /* DB has cache semantics */ + result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_db_load(db, TESTS_DIR "/testdata/db/data.db", + dns_masterformat_text, 0); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(dns_db_iscache(db)); + assert_false(dns_db_iszone(db)); + dns_db_detach(&db); +} + +/* database versions */ +ISC_RUN_TEST_IMPL(version) { + isc_result_t result; + dns_fixedname_t fname, ffound; + dns_name_t *name, *foundname; + dns_db_t *db = NULL; + dns_dbversion_t *ver = NULL, *new = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + + UNUSED(state); + + result = dns_test_loaddb(&db, dns_dbtype_zone, "test.test", + TESTS_DIR "/testdata/db/data.db"); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Open current version for reading */ + dns_db_currentversion(db, &ver); + dns_test_namefromstring("b.test.test", &fname); + name = dns_fixedname_name(&fname); + foundname = dns_fixedname_initname(&ffound); + dns_rdataset_init(&rdataset); + result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, &ver, false); + + /* Open new version for writing */ + dns_db_currentversion(db, &ver); + dns_test_namefromstring("b.test.test", &fname); + name = dns_fixedname_name(&fname); + foundname = dns_fixedname_initname(&ffound); + dns_rdataset_init(&rdataset); + result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_newversion(db, &new); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Delete the rdataset from the new version */ + result = dns_db_deleterdataset(db, node, new, dns_rdatatype_a, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + + /* This should fail now */ + result = dns_db_find(db, name, new, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + assert_int_equal(result, DNS_R_NXDOMAIN); + + dns_db_closeversion(db, &new, true); + + /* But this should still succeed */ + result = dns_db_find(db, name, ver, dns_rdatatype_a, 0, 0, &node, + foundname, &rdataset, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, &ver, false); + + dns_db_detach(&db); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(getoriginnode) +ISC_TEST_ENTRY(getsetservestalettl) +ISC_TEST_ENTRY(dns_dbfind_staleok) +ISC_TEST_ENTRY(class) +ISC_TEST_ENTRY(dbtype) +ISC_TEST_ENTRY(version) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dbdiff_test.c b/tests/dns/dbdiff_test.c new file mode 100644 index 0000000..f0fb880 --- /dev/null +++ b/tests/dns/dbdiff_test.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/journal.h> +#include <dns/name.h> + +#include <tests/dns.h> + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +static void +test_create(const char *oldfile, dns_db_t **old, const char *newfile, + dns_db_t **newdb) { + isc_result_t result; + + result = dns_test_loaddb(old, dns_dbtype_zone, TEST_ORIGIN, oldfile); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(newdb, dns_dbtype_zone, TEST_ORIGIN, newfile); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* dns_db_diffx of identical content */ +ISC_RUN_TEST_IMPL(diffx_same) { + dns_db_t *newdb = NULL, *olddb = NULL; + isc_result_t result; + dns_diff_t diff; + + UNUSED(state); + + test_create(TESTS_DIR "/testdata/diff/zone1.data", &olddb, + TESTS_DIR "/testdata/diff/zone1.data", &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_true(ISC_LIST_EMPTY(diff.tuples)); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); +} + +/* dns_db_diffx of zone with record added */ +ISC_RUN_TEST_IMPL(diffx_add) { + dns_db_t *newdb = NULL, *olddb = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + UNUSED(state); + + test_create(TESTS_DIR "/testdata/diff/zone1.data", &olddb, + TESTS_DIR "/testdata/diff/zone2.data", &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(ISC_LIST_EMPTY(diff.tuples)); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) + { + assert_int_equal(tuple->op, DNS_DIFFOP_ADD); + count++; + } + assert_int_equal(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); +} + +/* dns_db_diffx of zone with record removed */ +ISC_RUN_TEST_IMPL(diffx_remove) { + dns_db_t *newdb = NULL, *olddb = NULL; + dns_difftuple_t *tuple; + isc_result_t result; + dns_diff_t diff; + int count = 0; + + UNUSED(state); + + test_create(TESTS_DIR "/testdata/diff/zone1.data", &olddb, + TESTS_DIR "/testdata/diff/zone3.data", &newdb); + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, newdb, NULL, olddb, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(ISC_LIST_EMPTY(diff.tuples)); + for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) + { + assert_int_equal(tuple->op, DNS_DIFFOP_DEL); + count++; + } + assert_int_equal(count, 1); + + dns_diff_clear(&diff); + dns_db_detach(&newdb); + dns_db_detach(&olddb); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(diffx_same) +ISC_TEST_ENTRY(diffx_add) +ISC_TEST_ENTRY(diffx_remove) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dbiterator_test.c b/tests/dns/dbiterator_test.c new file mode 100644 index 0000000..f0277b1 --- /dev/null +++ b/tests/dns/dbiterator_test.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/name.h> + +#include <tests/dns.h> + +#define BUFLEN 255 +#define BIGBUFLEN (64 * 1024) +#define TEST_ORIGIN "test" + +static isc_result_t +make_name(const char *src, dns_name_t *name) { + isc_buffer_t b; + isc_buffer_constinit(&b, src, strlen(src)); + isc_buffer_add(&b, strlen(src)); + return (dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); +} + +/* create: make sure we can create a dbiterator */ +static void +test_create(const char *filename) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(create) { + UNUSED(state); + + test_create(TESTS_DIR "/testdata/dbiterator/zone1.data"); +} + +ISC_RUN_TEST_IMPL(create_nsec3) { + UNUSED(state); + + test_create(TESTS_DIR "/testdata/dbiterator/zone2.data"); +} + +/* walk: walk a database */ +static void +test_walk(const char *filename, int nodes) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name; + dns_fixedname_t f; + int i = 0; + + name = dns_fixedname_initname(&f); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + for (result = dns_dbiterator_first(iter); result == ISC_R_SUCCESS; + result = dns_dbiterator_next(iter)) + { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) { + result = ISC_R_SUCCESS; + } + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + i++; + } + + assert_int_equal(i, nodes); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(walk) { + UNUSED(state); + + test_walk(TESTS_DIR "/testdata/dbiterator/zone1.data", 12); +} + +ISC_RUN_TEST_IMPL(walk_nsec3) { + UNUSED(state); + + test_walk(TESTS_DIR "/testdata/dbiterator/zone2.data", 33); +} + +/* reverse: walk database backwards */ +static void +test_reverse(const char *filename) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name; + dns_fixedname_t f; + int i = 0; + + name = dns_fixedname_initname(&f); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + for (result = dns_dbiterator_last(iter); result == ISC_R_SUCCESS; + result = dns_dbiterator_prev(iter)) + { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) { + result = ISC_R_SUCCESS; + } + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + i++; + } + + assert_int_equal(i, 12); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(reverse) { + UNUSED(state); + + test_reverse(TESTS_DIR "/testdata/dbiterator/zone1.data"); +} + +ISC_RUN_TEST_IMPL(reverse_nsec3) { + UNUSED(state); + + test_reverse(TESTS_DIR "/testdata/dbiterator/zone2.data"); +} + +/* seek: walk database starting at a particular node */ +static void +test_seek_node(const char *filename, int nodes) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_name_t *name, *seekname; + dns_fixedname_t f1, f2; + int i = 0; + + name = dns_fixedname_initname(&f1); + seekname = dns_fixedname_initname(&f2); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + result = make_name("c." TEST_ORIGIN, seekname); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + assert_int_equal(result, ISC_R_SUCCESS); + + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(iter, &node, name); + if (result == DNS_R_NEWORIGIN) { + result = ISC_R_SUCCESS; + } + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(iter); + i++; + } + + assert_int_equal(i, nodes); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(seek_node) { + UNUSED(state); + + test_seek_node(TESTS_DIR "/testdata/dbiterator/zone1.data", 9); +} + +ISC_RUN_TEST_IMPL(seek_node_nsec3) { + UNUSED(state); + + test_seek_node(TESTS_DIR "/testdata/dbiterator/zone2.data", 30); +} + +/* + * seek_emty: walk database starting at an empty nonterminal node + * (should fail) + */ +static void +test_seek_empty(const char *filename) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_name_t *seekname; + dns_fixedname_t f1; + + seekname = dns_fixedname_initname(&f1); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + result = make_name("d." TEST_ORIGIN, seekname); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + assert_int_equal(result, DNS_R_PARTIALMATCH); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(seek_empty) { + UNUSED(state); + + test_seek_empty(TESTS_DIR "/testdata/dbiterator/zone1.data"); +} + +ISC_RUN_TEST_IMPL(seek_empty_nsec3) { + UNUSED(state); + + test_seek_empty(TESTS_DIR "/testdata/dbiterator/zone2.data"); +} + +/* + * seek_nx: walk database starting at a nonexistent node + */ +static void +test_seek_nx(const char *filename) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbiterator_t *iter = NULL; + dns_name_t *seekname; + dns_fixedname_t f1; + + seekname = dns_fixedname_initname(&f1); + + result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN, filename); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_createiterator(db, 0, &iter); + assert_int_equal(result, ISC_R_SUCCESS); + + result = make_name("nonexistent." TEST_ORIGIN, seekname); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + assert_int_equal(result, DNS_R_PARTIALMATCH); + + result = make_name("nonexistent.", seekname); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dbiterator_seek(iter, seekname); + assert_int_equal(result, ISC_R_NOTFOUND); + + dns_dbiterator_destroy(&iter); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(seek_nx) { + UNUSED(state); + + test_seek_nx(TESTS_DIR "/testdata/dbiterator/zone1.data"); +} + +ISC_RUN_TEST_IMPL(seek_nx_nsec3) { + UNUSED(state); + + test_seek_nx(TESTS_DIR "/testdata/dbiterator/zone2.data"); +} + +/* + * XXX: + * dns_dbiterator API calls that are not yet part of this unit test: + * + * dns_dbiterator_pause + * dns_dbiterator_origin + * dns_dbiterator_setcleanmode + */ +ISC_TEST_LIST_START +ISC_TEST_ENTRY(create) +ISC_TEST_ENTRY(create_nsec3) +ISC_TEST_ENTRY(walk) +ISC_TEST_ENTRY(walk_nsec3) +ISC_TEST_ENTRY(reverse) +ISC_TEST_ENTRY(reverse_nsec3) +ISC_TEST_ENTRY(seek_node) +ISC_TEST_ENTRY(seek_node_nsec3) +ISC_TEST_ENTRY(seek_empty) +ISC_TEST_ENTRY(seek_empty_nsec3) +ISC_TEST_ENTRY(seek_nx) +ISC_TEST_ENTRY(seek_nx_nsec3) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dbversion_test.c b/tests/dns/dbversion_test.c new file mode 100644 index 0000000..4d52166 --- /dev/null +++ b/tests/dns/dbversion_test.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/file.h> +#include <isc/result.h> +#include <isc/serial.h> +#include <isc/stdtime.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/nsec3.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> +#include <dns/rdatasetiter.h> + +#include <tests/dns.h> + +static char tempname[11] = "dtXXXXXXXX"; +static dns_db_t *db1 = NULL, *db2 = NULL; +static dns_dbversion_t *v1 = NULL, *v2 = NULL; + +/* + * The code below enables us to trap assertion failures for testing + * purposes. local_callback() is set as the callback function for + * isc_assertion_failed(). It calls mock_assert() so that CMOCKA + * will be able to see it, then returns to the calling function via + * longjmp() so that the abort() call in isc_assertion_failed() will + * never be reached. Use check_assertion() to check for assertions + * instead of expect_assert_failure(). + */ +jmp_buf assertion; + +#define check_assertion(function_call) \ + do { \ + const int r = setjmp(assertion); \ + if (r == 0) { \ + expect_assert_failure(function_call); \ + } \ + } while (false); + +static void +local_callback(const char *file, int line, isc_assertiontype_t type, + const char *cond) { + UNUSED(type); + + mock_assert(1, cond, file, line); + longjmp(assertion, 1); +} + +static int +setup_test(void **state) { + isc_result_t res; + + UNUSED(state); + + isc_assertion_setcallback(local_callback); + + res = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db1); + assert_int_equal(res, ISC_R_SUCCESS); + dns_db_newversion(db1, &v1); + assert_non_null(v1); + + res = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db2); + assert_int_equal(res, ISC_R_SUCCESS); + dns_db_newversion(db2, &v2); + assert_non_null(v1); + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + if (strcmp(tempname, "dtXXXXXXXX") != 0) { + unlink(tempname); + } + + if (v1 != NULL) { + dns_db_closeversion(db1, &v1, false); + assert_null(v1); + } + if (db1 != NULL) { + dns_db_detach(&db1); + assert_null(db1); + } + + if (v2 != NULL) { + dns_db_closeversion(db2, &v2, false); + assert_null(v2); + } + if (db2 != NULL) { + dns_db_detach(&db2); + assert_null(db2); + } + + return (0); +} + +/* + * Check dns_db_attachversion() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(attachversion) { + dns_dbversion_t *v = NULL; + + UNUSED(state); + + dns_db_attachversion(db1, v1, &v); + assert_ptr_equal(v, v1); + dns_db_closeversion(db1, &v, false); + assert_null(v); + + check_assertion(dns_db_attachversion(db1, v2, &v)); +} + +/* + * Check dns_db_closeversion() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(closeversion) { + UNUSED(state); + + assert_non_null(v1); + dns_db_closeversion(db1, &v1, false); + assert_null(v1); + + check_assertion(dns_db_closeversion(db1, &v2, false)); +} + +/* + * Check dns_db_find() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(find) { + isc_result_t res; + dns_rdataset_t rdataset; + dns_fixedname_t fixed; + dns_name_t *name = NULL; + + UNUSED(state); + + name = dns_fixedname_initname(&fixed); + + dns_rdataset_init(&rdataset); + res = dns_db_find(db1, dns_rootname, v1, dns_rdatatype_soa, 0, 0, NULL, + name, &rdataset, NULL); + assert_int_equal(res, DNS_R_NXDOMAIN); + + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + + dns_rdataset_init(&rdataset); + check_assertion((void)dns_db_find(db1, dns_rootname, v2, + dns_rdatatype_soa, 0, 0, NULL, name, + &rdataset, NULL)); +} + +/* + * Check dns_db_allrdatasets() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(allrdatasets) { + isc_result_t res; + dns_dbnode_t *node = NULL; + dns_rdatasetiter_t *iterator = NULL; + + UNUSED(state); + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_allrdatasets(db1, node, v1, 0, 0, &iterator); + assert_int_equal(res, ISC_R_SUCCESS); + + check_assertion(dns_db_allrdatasets(db1, node, v2, 0, 0, &iterator)); + + dns_rdatasetiter_destroy(&iterator); + assert_null(iterator); + + dns_db_detachnode(db1, &node); + assert_null(node); +} + +/* + * Check dns_db_findrdataset() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(findrdataset) { + isc_result_t res; + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; + + UNUSED(state); + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + dns_rdataset_init(&rdataset); + res = dns_db_findrdataset(db1, node, v1, dns_rdatatype_soa, 0, 0, + &rdataset, NULL); + assert_int_equal(res, ISC_R_NOTFOUND); + + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + + dns_rdataset_init(&rdataset); + check_assertion(dns_db_findrdataset(db1, node, v2, dns_rdatatype_soa, 0, + 0, &rdataset, NULL)); + + dns_db_detachnode(db1, &node); + assert_null(node); +} + +/* + * Check dns_db_deleterdataset() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(deleterdataset) { + isc_result_t res; + dns_dbnode_t *node = NULL; + + UNUSED(state); + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_deleterdataset(db1, node, v1, dns_rdatatype_soa, 0); + assert_int_equal(res, DNS_R_UNCHANGED); + + check_assertion( + dns_db_deleterdataset(db1, node, v2, dns_rdatatype_soa, 0)); + dns_db_detachnode(db1, &node); + assert_null(node); +} + +/* + * Check dns_db_subtractrdataset() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(subtract) { + isc_result_t res; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_dbnode_t *node = NULL; + + UNUSED(state); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + + rdatalist.rdclass = dns_rdataclass_in; + + res = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_subtractrdataset(db1, node, v1, &rdataset, 0, NULL); + assert_int_equal(res, DNS_R_UNCHANGED); + + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + + dns_rdataset_init(&rdataset); + res = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(res, ISC_R_SUCCESS); + + check_assertion( + dns_db_subtractrdataset(db1, node, v2, &rdataset, 0, NULL)); + + dns_db_detachnode(db1, &node); + assert_null(node); +} + +/* + * Check dns_db_dump() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(dump) { + isc_result_t res; + FILE *f = NULL; + + UNUSED(state); + + res = isc_file_openunique(tempname, &f); + fclose(f); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_dump(db1, v1, tempname); + assert_int_equal(res, ISC_R_SUCCESS); + + check_assertion(dns_db_dump(db1, v2, tempname)); +} + +/* + * Check dns_db_addrdataset() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(addrdataset) { + isc_result_t res; + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + + UNUSED(state); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + + rdatalist.rdclass = dns_rdataclass_in; + + res = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, NULL); + assert_int_equal(res, ISC_R_SUCCESS); + + check_assertion( + dns_db_addrdataset(db1, node, v2, 0, &rdataset, 0, NULL)); + + dns_db_detachnode(db1, &node); + assert_null(node); +} + +/* + * Check dns_db_getnsec3parameters() passes with matching db and version, + * and asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(getnsec3parameters) { + isc_result_t res; + dns_hash_t hash; + uint8_t flags; + uint16_t iterations; + unsigned char salt[DNS_NSEC3_SALTSIZE]; + size_t salt_length = sizeof(salt); + + UNUSED(state); + + res = dns_db_getnsec3parameters(db1, v1, &hash, &flags, &iterations, + salt, &salt_length); + assert_int_equal(res, ISC_R_NOTFOUND); + + check_assertion(dns_db_getnsec3parameters( + db1, v2, &hash, &flags, &iterations, salt, &salt_length)); +} + +/* + * Check dns_db_resigned() passes with matching db and version, and + * asserts with mis-matching db and version. + */ +ISC_RUN_TEST_IMPL(resigned) { + isc_result_t res; + dns_rdataset_t rdataset, added; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + dns_rdata_rrsig_t rrsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t b; + unsigned char buf[1024]; + + UNUSED(state); + + /* + * Create a dummy RRSIG record and set a resigning time. + */ + dns_rdataset_init(&added); + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + isc_buffer_init(&b, buf, sizeof(buf)); + + DNS_RDATACOMMON_INIT(&rrsig, dns_rdatatype_rrsig, dns_rdataclass_in); + rrsig.covered = dns_rdatatype_a; + rrsig.algorithm = 100; + rrsig.labels = 0; + rrsig.originalttl = 0; + rrsig.timeexpire = 3600; + rrsig.timesigned = 0; + rrsig.keyid = 0; + dns_name_init(&rrsig.signer, NULL); + dns_name_clone(dns_rootname, &rrsig.signer); + rrsig.siglen = 0; + rrsig.signature = NULL; + + res = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, + dns_rdatatype_rrsig, &rrsig, &b); + assert_int_equal(res, ISC_R_SUCCESS); + + rdatalist.rdclass = dns_rdataclass_in; + rdatalist.type = dns_rdatatype_rrsig; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + res = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(res, ISC_R_SUCCESS); + + rdataset.attributes |= DNS_RDATASETATTR_RESIGN; + rdataset.resign = 7200; + + res = dns_db_findnode(db1, dns_rootname, false, &node); + assert_int_equal(res, ISC_R_SUCCESS); + + res = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, &added); + assert_int_equal(res, ISC_R_SUCCESS); + + dns_db_detachnode(db1, &node); + assert_null(node); + + check_assertion(dns_db_resigned(db1, &added, v2)); + + dns_db_resigned(db1, &added, v1); + + dns_rdataset_disassociate(&added); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(dump, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(find, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(allrdatasets, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(findrdataset, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(deleterdataset, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(subtract, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(addrdataset, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(getnsec3parameters, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(resigned, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(attachversion, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(closeversion, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dh_test.c b/tests/dns/dh_test.c new file mode 100644 index 0000000..5f4edd9 --- /dev/null +++ b/tests/dns/dh_test.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/result.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/name.h> + +#include "dst_internal.h" + +#include <tests/dns.h> + +static int +setup_test(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dst_lib_init(mctx, NULL); + + if (result != ISC_R_SUCCESS) { + return (1); + } + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +/* OpenSSL DH_compute_key() failure */ +ISC_RUN_TEST_IMPL(dh_computesecret) { + dst_key_t *key = NULL; + isc_buffer_t buf; + unsigned char array[1024]; + isc_result_t result; + dns_fixedname_t fname; + dns_name_t *name; + + UNUSED(state); + + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&buf, "dh.", 3); + isc_buffer_add(&buf, 3); + result = dns_name_fromtext(name, &buf, NULL, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dst_key_fromfile(name, 18602, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_KEY, TESTS_DIR, + mctx, &key); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&buf, array, sizeof(array)); + result = dst_key_computesecret(key, key, &buf); + assert_int_equal(result, DST_R_NOTPRIVATEKEY); + result = key->func->computesecret(key, key, &buf); + assert_int_equal(result, DST_R_COMPUTESECRETFAILURE); + + dst_key_free(&key); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(dh_computesecret, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dispatch_test.c b/tests/dns/dispatch_test.c new file mode 100644 index 0000000..c101744 --- /dev/null +++ b/tests/dns/dispatch_test.c @@ -0,0 +1,698 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <uv.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/managers.h> +#include <isc/refcount.h> +#include <isc/task.h> +#include <isc/util.h> + +#include <dns/dispatch.h> +#include <dns/name.h> +#include <dns/view.h> + +#include <tests/dns.h> + +uv_sem_t sem; + +/* Timeouts in miliseconds */ +#define T_SERVER_INIT 5000 +#define T_SERVER_IDLE 5000 +#define T_SERVER_KEEPALIVE 5000 +#define T_SERVER_ADVERTISED 5000 + +#define T_CLIENT_INIT 2000 +#define T_CLIENT_IDLE 2000 +#define T_CLIENT_KEEPALIVE 2000 +#define T_CLIENT_ADVERTISED 2000 + +#define T_CLIENT_CONNECT 1000 + +dns_dispatchmgr_t *dispatchmgr = NULL; +dns_dispatchset_t *dset = NULL; +isc_nm_t *connect_nm = NULL; +static isc_sockaddr_t udp_server_addr; +static isc_sockaddr_t udp_connect_addr; +static isc_sockaddr_t tcp_server_addr; +static isc_sockaddr_t tcp_connect_addr; + +const struct in6_addr in6addr_blackhole = { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1 } } }; + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + socklen_t addrlen = sizeof(*addr); + uv_os_sock_t fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + close(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + close(fd); + return (r); + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + close(fd); + return (r); + } +#endif + + return (fd); +} + +static void +reset_testdata(void); + +static int +_setup(void **state) { + uv_os_sock_t sock = -1; + int r; + + udp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0); + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + + udp_server_addr = (isc_sockaddr_t){ .length = 0 }; + sock = setup_ephemeral_port(&udp_server_addr, SOCK_DGRAM); + if (sock < 0) { + return (-1); + } + close(sock); + + tcp_server_addr = (isc_sockaddr_t){ .length = 0 }; + sock = setup_ephemeral_port(&tcp_server_addr, SOCK_STREAM); + if (sock < 0) { + return (-1); + } + close(sock); + + setup_managers(state); + + /* Create a secondary network manager */ + isc_managers_create(mctx, workers, 0, &connect_nm, NULL, NULL); + + isc_nm_settimeouts(netmgr, T_SERVER_INIT, T_SERVER_IDLE, + T_SERVER_KEEPALIVE, T_SERVER_ADVERTISED); + + /* + * Use shorter client-side timeouts, to ensure that clients + * time out before the server. + */ + isc_nm_settimeouts(connect_nm, T_CLIENT_INIT, T_CLIENT_IDLE, + T_CLIENT_KEEPALIVE, T_CLIENT_ADVERTISED); + + r = uv_sem_init(&sem, 0); + assert_int_equal(r, 0); + + reset_testdata(); + + return (0); +} + +static int +_teardown(void **state) { + uv_sem_destroy(&sem); + + isc_managers_destroy(&connect_nm, NULL, NULL); + assert_null(connect_nm); + + teardown_managers(state); + + return (0); +} + +static isc_result_t +make_dispatchset(unsigned int ndisps) { + isc_result_t result; + isc_sockaddr_t any; + dns_dispatch_t *disp = NULL; + + result = dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr); + if (result != ISC_R_SUCCESS) { + return (result); + } + + isc_sockaddr_any(&any); + result = dns_dispatch_createudp(dispatchmgr, &any, &disp); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_dispatchset_create(mctx, disp, &dset, ndisps); + dns_dispatch_detach(&disp); + + return (result); +} + +static void +reset(void) { + if (dset != NULL) { + dns_dispatchset_destroy(&dset); + } + if (dispatchmgr != NULL) { + dns_dispatchmgr_detach(&dispatchmgr); + } +} + +/* create dispatch set */ +ISC_RUN_TEST_IMPL(dispatchset_create) { + isc_result_t result; + + UNUSED(state); + + result = make_dispatchset(1); + assert_int_equal(result, ISC_R_SUCCESS); + reset(); + + result = make_dispatchset(10); + assert_int_equal(result, ISC_R_SUCCESS); + reset(); +} + +/* test dispatch set round-robin */ +ISC_RUN_TEST_IMPL(dispatchset_get) { + isc_result_t result; + dns_dispatch_t *d1, *d2, *d3, *d4, *d5; + + UNUSED(state); + + result = make_dispatchset(1); + assert_int_equal(result, ISC_R_SUCCESS); + + d1 = dns_dispatchset_get(dset); + d2 = dns_dispatchset_get(dset); + d3 = dns_dispatchset_get(dset); + d4 = dns_dispatchset_get(dset); + d5 = dns_dispatchset_get(dset); + + assert_ptr_equal(d1, d2); + assert_ptr_equal(d2, d3); + assert_ptr_equal(d3, d4); + assert_ptr_equal(d4, d5); + + reset(); + + result = make_dispatchset(4); + assert_int_equal(result, ISC_R_SUCCESS); + + d1 = dns_dispatchset_get(dset); + d2 = dns_dispatchset_get(dset); + d3 = dns_dispatchset_get(dset); + d4 = dns_dispatchset_get(dset); + d5 = dns_dispatchset_get(dset); + + assert_ptr_equal(d1, d5); + assert_ptr_not_equal(d1, d2); + assert_ptr_not_equal(d2, d3); + assert_ptr_not_equal(d3, d4); + assert_ptr_not_equal(d4, d5); + + reset(); +} + +struct { + atomic_uint_fast32_t responses; + atomic_uint_fast32_t result; +} testdata; + +static dns_dispatch_t *dispatch = NULL; +static dns_dispentry_t *dispentry = NULL; +static atomic_bool first = true; + +static void +reset_testdata(void) { + atomic_init(&testdata.responses, 0); + atomic_init(&testdata.result, ISC_R_UNSET); +} + +static void +server_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(cbarg); + + return; +} + +static void +nameserver(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *cbarg) { + isc_region_t response; + static unsigned char buf1[16]; + static unsigned char buf2[16]; + + UNUSED(eresult); + UNUSED(cbarg); + + memmove(buf1, region->base, 12); + memset(buf1 + 12, 0, 4); + buf1[2] |= 0x80; /* qr=1 */ + + memmove(buf2, region->base, 12); + memset(buf2 + 12, 1, 4); + buf2[2] |= 0x80; /* qr=1 */ + + /* + * send message to be discarded. + */ + response.base = buf1; + response.length = sizeof(buf1); + isc_nm_send(handle, &response, server_senddone, NULL); + + /* + * send nextitem message. + */ + response.base = buf2; + response.length = sizeof(buf2); + isc_nm_send(handle, &response, server_senddone, NULL); +} + +static isc_result_t +accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(cbarg); + + return (eresult); +} + +static void +noop_nameserver(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(region); + UNUSED(cbarg); +} + +static void +response_getnext(isc_result_t result, isc_region_t *region, void *arg) { + UNUSED(region); + UNUSED(arg); + + atomic_fetch_add_relaxed(&testdata.responses, 1); + + if (atomic_compare_exchange_strong(&first, &(bool){ true }, false)) { + result = dns_dispatch_getnext(dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + } else { + uv_sem_post(&sem); + } +} + +static void +response(isc_result_t eresult, isc_region_t *region, void *arg) { + UNUSED(region); + UNUSED(arg); + + switch (eresult) { + case ISC_R_EOF: + case ISC_R_CANCELED: + case ISC_R_SHUTTINGDOWN: + break; + default: + atomic_fetch_add_relaxed(&testdata.responses, 1); + atomic_store_relaxed(&testdata.result, eresult); + } + + uv_sem_post(&sem); +} + +static void +response_timeout(isc_result_t eresult, isc_region_t *region, void *arg) { + UNUSED(region); + UNUSED(arg); + + atomic_store_relaxed(&testdata.result, eresult); + + uv_sem_post(&sem); +} + +static void +connected(isc_result_t eresult, isc_region_t *region, void *cbarg) { + isc_region_t *r = (isc_region_t *)cbarg; + + UNUSED(eresult); + UNUSED(region); + + dns_dispatch_send(dispentry, r); +} + +static void +client_senddone(isc_result_t eresult, isc_region_t *region, void *cbarg) { + UNUSED(eresult); + UNUSED(region); + UNUSED(cbarg); + + return; +} + +static void +timeout_connected(isc_result_t eresult, isc_region_t *region, void *cbarg) { + UNUSED(region); + UNUSED(cbarg); + + atomic_store_relaxed(&testdata.result, eresult); + + uv_sem_post(&sem); +} + +ISC_RUN_TEST_IMPL(dispatch_timeout_tcp_connect) { + isc_result_t result; + isc_region_t region; + unsigned char rbuf[12] = { 0 }; + unsigned char message[12] = { 0 }; + uint16_t id; + + UNUSED(state); + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_blackhole, 0); + + result = dns_dispatchmgr_create(mctx, connect_nm, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr, + &tcp_server_addr, &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + region.base = rbuf; + region.length = sizeof(rbuf); + + result = dns_dispatch_add(dispatch, 0, T_CLIENT_CONNECT, + &tcp_server_addr, timeout_connected, + client_senddone, response, ®ion, &id, + &dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + + dns_dispatch_connect(dispentry); + + uv_sem_wait(&sem); + + dns_dispatch_done(&dispentry); + + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_detach(&dispatchmgr); + + /* Skip if the IPv6 is not available or not blackholed */ + + result = atomic_load_acquire(&testdata.result); + if (result == ISC_R_ADDRNOTAVAIL || result == ISC_R_CONNREFUSED) { + skip(); + return; + } + + assert_int_equal(result, ISC_R_TIMEDOUT); +} + +ISC_RUN_TEST_IMPL(dispatch_timeout_tcp_response) { + isc_result_t result; + isc_region_t region; + unsigned char rbuf[12] = { 0 }; + unsigned char message[12] = { 0 }; + uint16_t id; + isc_nmsocket_t *sock = NULL; + + UNUSED(state); + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + + result = dns_dispatchmgr_create(mctx, connect_nm, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr, + &tcp_server_addr, &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listentcpdns(netmgr, &tcp_server_addr, noop_nameserver, + NULL, accept_cb, NULL, 0, 0, NULL, &sock); + assert_int_equal(result, ISC_R_SUCCESS); + + region.base = rbuf; + region.length = sizeof(rbuf); + + result = dns_dispatch_add(dispatch, 0, T_CLIENT_CONNECT, + &tcp_server_addr, connected, client_senddone, + response_timeout, ®ion, &id, &dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + + dns_dispatch_connect(dispentry); + + uv_sem_wait(&sem); + + assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_TIMEDOUT); + + isc_nm_stoplistening(sock); + isc_nmsocket_close(&sock); + assert_null(sock); + + dns_dispatch_done(&dispentry); + + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_detach(&dispatchmgr); +} + +ISC_RUN_TEST_IMPL(dispatch_tcp_response) { + isc_result_t result; + isc_region_t region; + unsigned char rbuf[12] = { 0 }; + unsigned char message[12] = { 0 }; + uint16_t id; + isc_nmsocket_t *sock = NULL; + + UNUSED(state); + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + + result = dns_dispatchmgr_create(mctx, connect_nm, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr, + &tcp_server_addr, &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listentcpdns(netmgr, &tcp_server_addr, nameserver, NULL, + accept_cb, NULL, 0, 0, NULL, &sock); + assert_int_equal(result, ISC_R_SUCCESS); + + region.base = rbuf; + region.length = sizeof(rbuf); + + result = dns_dispatch_add(dispatch, 0, T_CLIENT_CONNECT, + &tcp_server_addr, connected, client_senddone, + response, ®ion, &id, &dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + + dns_dispatch_connect(dispentry); + + uv_sem_wait(&sem); + + assert_in_range(atomic_load_acquire(&testdata.responses), 1, 2); + assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_SUCCESS); + + /* Cleanup */ + + isc_nm_stoplistening(sock); + isc_nmsocket_close(&sock); + assert_null(sock); + + dns_dispatch_done(&dispentry); + + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_detach(&dispatchmgr); +} + +ISC_RUN_TEST_IMPL(dispatch_timeout_udp_response) { + isc_result_t result; + isc_region_t region; + unsigned char rbuf[12] = { 0 }; + unsigned char message[12] = { 0 }; + uint16_t id; + isc_nmsocket_t *sock = NULL; + + UNUSED(state); + + udp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0); + + result = dns_dispatchmgr_create(mctx, connect_nm, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dispatch_createudp(dispatchmgr, &tcp_connect_addr, + &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenudp(netmgr, &udp_server_addr, noop_nameserver, + NULL, 0, &sock); + assert_int_equal(result, ISC_R_SUCCESS); + + region.base = rbuf; + region.length = sizeof(rbuf); + + result = dns_dispatch_add(dispatch, 0, T_CLIENT_CONNECT, + &udp_server_addr, connected, client_senddone, + response_timeout, ®ion, &id, &dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + + dns_dispatch_connect(dispentry); + + uv_sem_wait(&sem); + + assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_TIMEDOUT); + + isc_nm_stoplistening(sock); + isc_nmsocket_close(&sock); + assert_null(sock); + + dns_dispatch_done(&dispentry); + + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_detach(&dispatchmgr); +} + +/* test dispatch getnext */ +ISC_RUN_TEST_IMPL(dispatch_getnext) { + isc_result_t result; + isc_region_t region; + isc_nmsocket_t *sock = NULL; + unsigned char message[12] = { 0 }; + unsigned char rbuf[12] = { 0 }; + uint16_t id; + + UNUSED(state); + + result = dns_dispatchmgr_create(mctx, connect_nm, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dispatch_createudp(dispatchmgr, &udp_connect_addr, + &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Create a local udp nameserver on the loopback. + */ + result = isc_nm_listenudp(netmgr, &udp_server_addr, nameserver, NULL, 0, + &sock); + assert_int_equal(result, ISC_R_SUCCESS); + + region.base = rbuf; + region.length = sizeof(rbuf); + result = dns_dispatch_add(dispatch, 0, T_CLIENT_CONNECT, + &udp_server_addr, connected, client_senddone, + response_getnext, ®ion, &id, &dispentry); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(message, 0, sizeof(message)); + message[0] = (id >> 8) & 0xff; + message[1] = id & 0xff; + + region.base = message; + region.length = sizeof(message); + + dns_dispatch_connect(dispentry); + + uv_sem_wait(&sem); + + assert_int_equal(atomic_load_acquire(&testdata.responses), 2); + + /* Cleanup */ + isc_nm_stoplistening(sock); + isc_nmsocket_close(&sock); + assert_null(sock); + + dns_dispatch_done(&dispentry); + dns_dispatch_detach(&dispatch); + dns_dispatchmgr_detach(&dispatchmgr); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dispatch_timeout_tcp_connect, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatch_timeout_tcp_response, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatch_tcp_response, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatch_timeout_udp_response, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatchset_create, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatchset_get, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dispatch_getnext, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dns64_test.c b/tests/dns/dns64_test.c new file mode 100644 index 0000000..5834991 --- /dev/null +++ b/tests/dns/dns64_test.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/netaddr.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/dns64.h> +#include <dns/rdata.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> + +#include <tests/dns.h> + +static void +multiple_prefixes(void) { + size_t i, count; + /* + * Two prefix, non consectutive. + */ + unsigned char aaaa[4][16] = { + { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 }, + { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 }, + { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 }, + { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 }, + }; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata[4] = { DNS_RDATA_INIT, DNS_RDATA_INIT, DNS_RDATA_INIT, + DNS_RDATA_INIT }; + isc_netprefix_t prefix[2]; + unsigned char p1[] = { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 }; + unsigned char p2[] = { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0 }; + isc_result_t result; + bool have_p1, have_p2; + + /* + * Construct AAAA rdataset containing 2 prefixes. + */ + dns_rdatalist_init(&rdatalist); + for (i = 0; i < 4; i++) { + isc_region_t region; + region.base = aaaa[i]; + region.length = 16; + dns_rdata_fromregion(&rdata[i], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link); + } + rdatalist.type = rdata[0].type; + rdatalist.rdclass = rdata[0].rdclass; + rdatalist.ttl = 0; + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + count = ARRAY_SIZE(prefix); + memset(&prefix, 0, sizeof(prefix)); + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(count, 2); + have_p1 = have_p2 = false; + for (i = 0; i < count; i++) { + assert_int_equal(prefix[i].prefixlen, 96); + assert_int_equal(prefix[i].addr.family, AF_INET6); + if (memcmp(prefix[i].addr.type.in6.s6_addr, p1, 12) == 0) { + have_p1 = true; + } + if (memcmp(prefix[i].addr.type.in6.s6_addr, p2, 12) == 0) { + have_p2 = true; + } + } + assert_true(have_p1); + assert_true(have_p2); + + /* + * Check that insufficient prefix space returns ISC_R_NOSPACE + * and that the prefix is populated. + */ + count = 1; + memset(&prefix, 0, sizeof(prefix)); + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, ISC_R_NOSPACE); + assert_int_equal(count, 2); + have_p1 = have_p2 = false; + assert_int_equal(prefix[0].prefixlen, 96); + assert_int_equal(prefix[0].addr.family, AF_INET6); + if (memcmp(prefix[0].addr.type.in6.s6_addr, p1, 12) == 0) { + have_p1 = true; + } + if (memcmp(prefix[0].addr.type.in6.s6_addr, p2, 12) == 0) { + have_p2 = true; + } + if (!have_p2) { + assert_true(have_p1); + } + if (!have_p1) { + assert_true(have_p2); + } + assert_true(have_p1 != have_p2); +} + +ISC_RUN_TEST_IMPL(dns64_findprefix) { + unsigned int i, j, o; + isc_result_t result; + struct { + unsigned char prefix[12]; + unsigned int prefixlen; + isc_result_t result; + } tests[] = { + /* The WKP with various lengths. */ + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 32, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 40, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 48, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 56, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 64, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + /* + * Prefix with the mapped addresses also appearing in the + * prefix. + */ + { { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + { { 0, 0, 0, 0, 192, 0, 0, 171, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + /* Bad prefix, MBZ != 0. */ + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 1, 0, 0, 0 }, + 96, + ISC_R_NOTFOUND }, + }; + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + size_t count = 2; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata[2] = { DNS_RDATA_INIT, DNS_RDATA_INIT }; + struct in6_addr ina6[2]; + isc_netprefix_t prefix[2]; + unsigned char aa[] = { 192, 0, 0, 170 }; + unsigned char ab[] = { 192, 0, 0, 171 }; + isc_region_t region; + + /* + * Construct rdata. + */ + memset(ina6[0].s6_addr, 0, sizeof(ina6[0].s6_addr)); + memset(ina6[1].s6_addr, 0, sizeof(ina6[1].s6_addr)); + memmove(ina6[0].s6_addr, tests[i].prefix, 12); + memmove(ina6[1].s6_addr, tests[i].prefix, 12); + o = tests[i].prefixlen / 8; + for (j = 0; j < 4; j++) { + if ((o + j) == 8U) { + o++; /* skip mbz */ + } + ina6[0].s6_addr[j + o] = aa[j]; + ina6[1].s6_addr[j + o] = ab[j]; + } + region.base = ina6[0].s6_addr; + region.length = sizeof(ina6[0].s6_addr); + dns_rdata_fromregion(&rdata[0], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + region.base = ina6[1].s6_addr; + region.length = sizeof(ina6[1].s6_addr); + dns_rdata_fromregion(&rdata[1], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + + dns_rdatalist_init(&rdatalist); + rdatalist.type = rdata[0].type; + rdatalist.rdclass = rdata[0].rdclass; + rdatalist.ttl = 0; + ISC_LIST_APPEND(rdatalist.rdata, &rdata[0], link); + ISC_LIST_APPEND(rdatalist.rdata, &rdata[1], link); + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, tests[i].result); + if (tests[i].result == ISC_R_SUCCESS) { + assert_int_equal(count, 1); + assert_int_equal(prefix[0].prefixlen, + tests[i].prefixlen); + assert_int_equal(prefix[0].addr.family, AF_INET6); + assert_memory_equal(prefix[0].addr.type.in6.s6_addr, + tests[i].prefix, + tests[i].prefixlen / 8); + } + } + + /* + * Test multiple prefixes. + */ + multiple_prefixes(); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(dns64_findprefix) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dnstap_test.c b/tests/dns/dnstap_test.c new file mode 100644 index 0000000..73b3304 --- /dev/null +++ b/tests/dns/dnstap_test.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> +#include <fstrm.h> + +#include <protobuf-c/protobuf-c.h> + +#include <isc/buffer.h> +#include <isc/file.h> +#include <isc/print.h> +#include <isc/stdio.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <dns/dnstap.h> +#include <dns/view.h> + +#include <tests/dns.h> + +#define TAPFILE TESTS_DIR "/testdata/dnstap/dnstap.file" +#define TAPSOCK TESTS_DIR "/testdata/dnstap/dnstap.sock" + +#define TAPSAVED TESTS_DIR "/testdata/dnstap/dnstap.saved" +#define TAPTEXT TESTS_DIR "/testdata/dnstap/dnstap.text" + +static int +cleanup(void **state __attribute__((__unused__))) { + (void)isc_file_remove(TAPFILE); + (void)isc_file_remove(TAPSOCK); + + return (0); +} + +static int +setup(void **state) { + /* + * Make sure files are cleaned up before the test runs. + */ + cleanup(state); + + /* + * Make sure text conversions match the time zone in which + * the testdata was originally generated. + */ + setenv("TZ", "PDT8", 1); + return (0); +} + +/* set up dnstap environment */ +ISC_RUN_TEST_IMPL(dns_dt_create) { + isc_result_t result; + dns_dtenv_t *dtenv = NULL; + struct fstrm_iothr_options *fopt; + + fopt = fstrm_iothr_options_init(); + assert_non_null(fopt); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, &fopt, NULL, + &dtenv); + assert_int_equal(result, ISC_R_SUCCESS); + if (dtenv != NULL) { + dns_dt_detach(&dtenv); + } + if (fopt != NULL) { + fstrm_iothr_options_destroy(&fopt); + } + + assert_true(isc_file_exists(TAPFILE)); + + fopt = fstrm_iothr_options_init(); + assert_non_null(fopt); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_unix, TAPSOCK, &fopt, NULL, + &dtenv); + assert_int_equal(result, ISC_R_SUCCESS); + if (dtenv != NULL) { + dns_dt_detach(&dtenv); + } + if (fopt != NULL) { + fstrm_iothr_options_destroy(&fopt); + } + + /* 'create' should succeed, but the file shouldn't exist yet */ + assert_false(isc_file_exists(TAPSOCK)); + + fopt = fstrm_iothr_options_init(); + assert_non_null(fopt); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, 33, TAPSOCK, &fopt, NULL, &dtenv); + assert_int_equal(result, ISC_R_FAILURE); + assert_null(dtenv); + if (dtenv != NULL) { + dns_dt_detach(&dtenv); + } + if (fopt != NULL) { + fstrm_iothr_options_destroy(&fopt); + } +} + +/* send dnstap messages */ +ISC_RUN_TEST_IMPL(dns_dt_send) { + isc_result_t result; + dns_dtenv_t *dtenv = NULL; + dns_dthandle_t *handle = NULL; + uint8_t *data; + size_t dsize; + unsigned char zone[DNS_NAME_MAXWIRE]; + unsigned char qambuffer[4096], rambuffer[4096]; + unsigned char qrmbuffer[4096], rrmbuffer[4096]; + isc_buffer_t zb, qamsg, ramsg, qrmsg, rrmsg; + size_t qasize, qrsize, rasize, rrsize; + dns_fixedname_t zfname; + dns_name_t *zname; + dns_dtmsgtype_t dt; + dns_view_t *view = NULL; + dns_compress_t cctx; + isc_region_t zr; + isc_sockaddr_t qaddr; + isc_sockaddr_t raddr; + struct in_addr in; + isc_stdtime_t now; + isc_time_t p, f; + struct fstrm_iothr_options *fopt; + + result = dns_test_makeview("test", false, &view); + assert_int_equal(result, ISC_R_SUCCESS); + + fopt = fstrm_iothr_options_init(); + assert_non_null(fopt); + fstrm_iothr_options_set_num_input_queues(fopt, 1); + + result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, &fopt, NULL, + &dtenv); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_dt_attach(dtenv, &view->dtenv); + view->dttypes = DNS_DTTYPE_ALL; + + /* + * Set up some test data + */ + zname = dns_fixedname_initname(&zfname); + isc_buffer_constinit(&zb, "example.com.", 12); + isc_buffer_add(&zb, 12); + result = dns_name_fromtext(zname, &zb, NULL, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&zr, 0, sizeof(zr)); + isc_buffer_init(&zb, zone, sizeof(zone)); + result = dns_compress_init(&cctx, -1, mctx); + assert_int_equal(result, ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE); + result = dns_name_towire(zname, &cctx, &zb); + assert_int_equal(result, ISC_R_SUCCESS); + dns_compress_invalidate(&cctx); + isc_buffer_usedregion(&zb, &zr); + + in.s_addr = inet_addr("10.53.0.1"); + isc_sockaddr_fromin(&qaddr, &in, 2112); + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&raddr, &in, 2112); + + isc_stdtime_get(&now); + isc_time_set(&p, now - 3600, 0); /* past */ + isc_time_set(&f, now + 3600, 0); /* future */ + + result = dns_test_getdata(TESTS_DIR "/testdata/dnstap/query.auth", + qambuffer, sizeof(qambuffer), &qasize); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&qamsg, qambuffer, qasize); + isc_buffer_add(&qamsg, qasize); + + result = dns_test_getdata(TESTS_DIR "/testdata/dnstap/response.auth", + rambuffer, sizeof(rambuffer), &rasize); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&ramsg, rambuffer, rasize); + isc_buffer_add(&ramsg, rasize); + + result = dns_test_getdata(TESTS_DIR "/testdata/dnstap/query.recursive", + qrmbuffer, sizeof(qrmbuffer), &qrsize); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&qrmsg, qrmbuffer, qrsize); + isc_buffer_add(&qrmsg, qrsize); + + result = dns_test_getdata(TESTS_DIR + "/testdata/dnstap/response.recursive", + rrmbuffer, sizeof(rrmbuffer), &rrsize); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&rrmsg, rrmbuffer, rrsize); + isc_buffer_add(&rrmsg, rrsize); + + for (dt = DNS_DTTYPE_SQ; dt <= DNS_DTTYPE_TR; dt <<= 1) { + isc_buffer_t *m; + isc_sockaddr_t *q = &qaddr, *r = &raddr; + + switch (dt) { + case DNS_DTTYPE_AQ: + m = &qamsg; + break; + case DNS_DTTYPE_AR: + m = &ramsg; + break; + default: + m = &qrmsg; + if ((dt & DNS_DTTYPE_RESPONSE) != 0) { + m = &ramsg; + } + break; + } + + dns_dt_send(view, dt, q, r, false, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, false, &zr, NULL, &f, m); + dns_dt_send(view, dt, q, r, false, &zr, &p, NULL, m); + dns_dt_send(view, dt, q, r, false, &zr, NULL, NULL, m); + dns_dt_send(view, dt, q, r, true, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, true, &zr, NULL, &f, m); + dns_dt_send(view, dt, q, r, true, &zr, &p, NULL, m); + dns_dt_send(view, dt, q, r, true, &zr, NULL, NULL, m); + } + + dns_dt_detach(&view->dtenv); + dns_dt_detach(&dtenv); + dns_view_detach(&view); + + result = dns_dt_open(TAPFILE, dns_dtmode_file, mctx, &handle); + assert_int_equal(result, ISC_R_SUCCESS); + + while (dns_dt_getframe(handle, &data, &dsize) == ISC_R_SUCCESS) { + dns_dtdata_t *dtdata = NULL; + isc_region_t r; + static dns_dtmsgtype_t expected = DNS_DTTYPE_SQ; + static int n = 0; + + r.base = data; + r.length = dsize; + + result = dns_dt_parse(mctx, &r, &dtdata); + assert_int_equal(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) { + n++; + continue; + } + + assert_int_equal(dtdata->type, expected); + if (++n % 8 == 0) { + expected <<= 1; + } + + dns_dtdata_free(&dtdata); + } + + if (fopt != NULL) { + fstrm_iothr_options_destroy(&fopt); + } + if (handle != NULL) { + dns_dt_close(&handle); + } +} + +/* dnstap message to text */ +ISC_RUN_TEST_IMPL(dns_dt_totext) { + isc_result_t result; + dns_dthandle_t *handle = NULL; + uint8_t *data; + size_t dsize; + FILE *fp = NULL; + + UNUSED(state); + + result = dns_dt_open(TAPSAVED, dns_dtmode_file, mctx, &handle); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_stdio_open(TAPTEXT, "r", &fp); + assert_int_equal(result, ISC_R_SUCCESS); + + while (dns_dt_getframe(handle, &data, &dsize) == ISC_R_SUCCESS) { + dns_dtdata_t *dtdata = NULL; + isc_buffer_t *b = NULL; + isc_region_t r; + char s[BUFSIZ], *p; + + r.base = data; + r.length = dsize; + + /* read the corresponding line of text */ + p = fgets(s, sizeof(s), fp); + assert_ptr_equal(p, s); + if (p == NULL) { + break; + } + + p = strchr(p, '\n'); + if (p != NULL) { + *p = '\0'; + } + + /* parse dnstap frame */ + result = dns_dt_parse(mctx, &r, &dtdata); + assert_int_equal(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) { + continue; + } + + isc_buffer_allocate(mctx, &b, 2048); + assert_non_null(b); + if (b == NULL) { + break; + } + + /* convert to text and compare */ + result = dns_dt_datatotext(dtdata, &b); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_string_equal((char *)isc_buffer_base(b), s); + + dns_dtdata_free(&dtdata); + isc_buffer_free(&b); + } + + if (handle != NULL) { + dns_dt_close(&handle); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_dt_create, setup, cleanup) +ISC_TEST_ENTRY_CUSTOM(dns_dt_send, setup, cleanup) +ISC_TEST_ENTRY_CUSTOM(dns_dt_totext, setup, cleanup) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/dst_test.c b/tests/dns/dst_test.c new file mode 100644 index 0000000..283a7ba --- /dev/null +++ b/tests/dns/dst_test.c @@ -0,0 +1,487 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/file.h> +#include <isc/hex.h> +#include <isc/result.h> +#include <isc/stdio.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dst/dst.h> + +#include "dst_internal.h" + +#include <tests/dns.h> + +static int +setup_test(void **state) { + UNUSED(state); + + dst_lib_init(mctx, NULL); + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +/* Read sig in file at path to buf. Check signature ineffability */ +static isc_result_t +sig_fromfile(const char *path, isc_buffer_t *buf) { + isc_result_t result; + size_t rval, len; + FILE *fp = NULL; + unsigned char val; + char *p, *data; + off_t size; + + result = isc_stdio_open(path, "rb", &fp); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_file_getsizefd(fileno(fp), &size); + assert_int_equal(result, ISC_R_SUCCESS); + + data = isc_mem_get(mctx, (size + 1)); + assert_non_null(data); + + len = (size_t)size; + p = data; + while (len != 0U) { + result = isc_stdio_read(p, 1, len, fp, &rval); + assert_int_equal(result, ISC_R_SUCCESS); + len -= rval; + p += rval; + } + isc_stdio_close(fp); + + p = data; + len = size; + while (len > 0U) { + if ((*p == '\r') || (*p == '\n')) { + ++p; + --len; + continue; + } else if (len < 2U) { + goto err; + } + if (('0' <= *p) && (*p <= '9')) { + val = *p - '0'; + } else if (('A' <= *p) && (*p <= 'F')) { + val = *p - 'A' + 10; + } else { + result = ISC_R_BADHEX; + goto err; + } + ++p; + val <<= 4; + --len; + if (('0' <= *p) && (*p <= '9')) { + val |= (*p - '0'); + } else if (('A' <= *p) && (*p <= 'F')) { + val |= (*p - 'A' + 10); + } else { + result = ISC_R_BADHEX; + goto err; + } + ++p; + --len; + isc_buffer_putuint8(buf, val); + } + + result = ISC_R_SUCCESS; + +err: + isc_mem_put(mctx, data, size + 1); + return (result); +} + +static void +check_sig(const char *datapath, const char *sigpath, const char *keyname, + dns_keytag_t id, dns_secalg_t alg, int type, bool expect) { + isc_result_t result; + size_t rval, len; + FILE *fp; + dst_key_t *key = NULL; + unsigned char sig[512]; + unsigned char *p; + unsigned char *data; + off_t size; + isc_buffer_t b; + isc_buffer_t databuf, sigbuf; + isc_region_t datareg, sigreg; + dns_fixedname_t fname; + dns_name_t *name; + dst_context_t *ctx = NULL; + + /* + * Read data from file in a form usable by dst_verify. + */ + result = isc_stdio_open(datapath, "rb", &fp); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_file_getsizefd(fileno(fp), &size); + assert_int_equal(result, ISC_R_SUCCESS); + + data = isc_mem_get(mctx, (size + 1)); + assert_non_null(data); + + p = data; + len = (size_t)size; + do { + result = isc_stdio_read(p, 1, len, fp, &rval); + assert_int_equal(result, ISC_R_SUCCESS); + len -= rval; + p += rval; + } while (len); + isc_stdio_close(fp); + + /* + * Read key from file in a form usable by dst_verify. + */ + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&b, keyname, strlen(keyname)); + isc_buffer_add(&b, strlen(keyname)); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dst_key_fromfile(name, id, alg, type, + TESTS_DIR "/testdata/dst", mctx, &key); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&databuf, data, (unsigned int)size); + isc_buffer_add(&databuf, (unsigned int)size); + isc_buffer_usedregion(&databuf, &datareg); + + memset(sig, 0, sizeof(sig)); + isc_buffer_init(&sigbuf, sig, sizeof(sig)); + + /* + * Read precomputed signature from file in a form usable by dst_verify. + */ + result = sig_fromfile(sigpath, &sigbuf); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Verify that the key signed the data. + */ + isc_buffer_remainingregion(&sigbuf, &sigreg); + + result = dst_context_create(key, mctx, DNS_LOGCATEGORY_GENERAL, false, + 0, &ctx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dst_context_adddata(ctx, &datareg); + assert_int_equal(result, ISC_R_SUCCESS); + result = dst_context_verify(ctx, &sigreg); + + /* + * Compute the expected signature and emit it + * so the precomputed signature can be updated. + * This should only be done if the covered data + * is updated. + */ + if (expect && result != ISC_R_SUCCESS) { + isc_result_t result2; + + dst_context_destroy(&ctx); + result2 = dst_context_create(key, mctx, DNS_LOGCATEGORY_GENERAL, + false, 0, &ctx); + assert_int_equal(result2, ISC_R_SUCCESS); + + result2 = dst_context_adddata(ctx, &datareg); + assert_int_equal(result2, ISC_R_SUCCESS); + + char sigbuf2[4096]; + isc_buffer_t sigb; + isc_buffer_init(&sigb, sigbuf2, sizeof(sigbuf2)); + + result2 = dst_context_sign(ctx, &sigb); + assert_int_equal(result2, ISC_R_SUCCESS); + + isc_region_t r; + isc_buffer_usedregion(&sigb, &r); + + char hexbuf[4096] = { 0 }; + isc_buffer_t hb; + isc_buffer_init(&hb, hexbuf, sizeof(hexbuf)); + + isc_hex_totext(&r, 0, "", &hb); + + fprintf(stderr, "# %s:\n# %s\n", sigpath, hexbuf); + } + + isc_mem_put(mctx, data, size + 1); + dst_context_destroy(&ctx); + dst_key_free(&key); + + assert_true((expect && (result == ISC_R_SUCCESS)) || + (!expect && (result != ISC_R_SUCCESS))); + + return; +} + +ISC_RUN_TEST_IMPL(sig_test) { + struct { + const char *datapath; + const char *sigpath; + const char *keyname; + dns_keytag_t keyid; + dns_secalg_t alg; + bool expect; + } testcases[] = { + { TESTS_DIR "/testdata/dst/test1.data", + TESTS_DIR "/testdata/dst/test1.ecdsa256sig", "test.", 49130, + DST_ALG_ECDSA256, true }, + { TESTS_DIR "/testdata/dst/test1.data", + TESTS_DIR "/testdata/dst/test1.rsasha256sig", "test.", 11349, + DST_ALG_RSASHA256, true }, + { /* wrong sig */ + TESTS_DIR "/testdata/dst/test1.data", + TESTS_DIR "/testdata/dst/test1.ecdsa256sig", "test.", 11349, + DST_ALG_RSASHA256, false }, + { /* wrong data */ + TESTS_DIR "/testdata/dst/test2.data", + TESTS_DIR "/testdata/dst/test1.ecdsa256sig", "test.", 49130, + DST_ALG_ECDSA256, false }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + if (!dst_algorithm_supported(testcases[i].alg)) { + continue; + } + + check_sig(testcases[i].datapath, testcases[i].sigpath, + testcases[i].keyname, testcases[i].keyid, + testcases[i].alg, DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, + testcases[i].expect); + } +} + +static void +check_cmp(const char *key1_name, dns_keytag_t key1_id, const char *key2_name, + dns_keytag_t key2_id, dns_secalg_t alg, int type, bool expect) { + isc_result_t result; + dst_key_t *key1 = NULL; + dst_key_t *key2 = NULL; + isc_buffer_t b1; + isc_buffer_t b2; + dns_fixedname_t fname1; + dns_fixedname_t fname2; + dns_name_t *name1; + dns_name_t *name2; + + /* + * Read key1 from the file. + */ + name1 = dns_fixedname_initname(&fname1); + isc_buffer_constinit(&b1, key1_name, strlen(key1_name)); + isc_buffer_add(&b1, strlen(key1_name)); + result = dns_name_fromtext(name1, &b1, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dst_key_fromfile(name1, key1_id, alg, type, + TESTS_DIR "/comparekeys", mctx, &key1); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Read key2 from the file. + */ + name2 = dns_fixedname_initname(&fname2); + isc_buffer_constinit(&b2, key2_name, strlen(key2_name)); + isc_buffer_add(&b2, strlen(key2_name)); + result = dns_name_fromtext(name2, &b2, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dst_key_fromfile(name2, key2_id, alg, type, + TESTS_DIR "/comparekeys", mctx, &key2); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Compare the keys (for public-only keys). + */ + if ((type & DST_TYPE_PRIVATE) == 0) { + assert_true(dst_key_pubcompare(key1, key2, false) == expect); + } + + /* + * Compare the keys (for both public-only keys and keypairs). + */ + assert_true(dst_key_compare(key1, key2) == expect); + + /* + * Free the keys + */ + dst_key_free(&key2); + dst_key_free(&key1); + + return; +} + +ISC_RUN_TEST_IMPL(cmp_test) { + struct { + const char *key1_name; + dns_keytag_t key1_id; + const char *key2_name; + dns_keytag_t key2_id; + dns_secalg_t alg; + int type; + bool expect; + } testcases[] = { + /* RSA Keypair: self */ + { "example.", 53461, "example.", 53461, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, true }, + + /* RSA Keypair: different key */ + { "example.", 53461, "example2.", 37993, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Keypair: different PublicExponent (e) */ + { "example.", 53461, "example-e.", 53973, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Keypair: different Modulus (n) */ + { "example.", 53461, "example-n.", 37464, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Keypair: different PrivateExponent (d) */ + { "example.", 53461, "example-d.", 53461, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Keypair: different Prime1 (p) */ + { "example.", 53461, "example-p.", 53461, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Keypair: different Prime2 (q) */ + { "example.", 53461, "example-q.", 53461, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* RSA Public Key: self */ + { "example.", 53461, "example.", 53461, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC, true }, + + /* RSA Public Key: different key */ + { "example.", 53461, "example2.", 37993, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC, false }, + + /* RSA Public Key: different PublicExponent (e) */ + { "example.", 53461, "example-e.", 53973, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC, false }, + + /* RSA Public Key: different Modulus (n) */ + { "example.", 53461, "example-n.", 37464, DST_ALG_RSASHA256, + DST_TYPE_PUBLIC, false }, + + /* ECDSA Keypair: self */ + { "example.", 19786, "example.", 19786, DST_ALG_ECDSA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, true }, + + /* ECDSA Keypair: different key */ + { "example.", 19786, "example2.", 16384, DST_ALG_ECDSA256, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* ECDSA Public Key: self */ + { "example.", 19786, "example.", 19786, DST_ALG_ECDSA256, + DST_TYPE_PUBLIC, true }, + + /* ECDSA Public Key: different key */ + { "example.", 19786, "example2.", 16384, DST_ALG_ECDSA256, + DST_TYPE_PUBLIC, false }, + + /* EdDSA Keypair: self */ + { "example.", 63663, "example.", 63663, DST_ALG_ED25519, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, true }, + + /* EdDSA Keypair: different key */ + { "example.", 63663, "example2.", 37529, DST_ALG_ED25519, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, false }, + + /* EdDSA Public Key: self */ + { "example.", 63663, "example.", 63663, DST_ALG_ED25519, + DST_TYPE_PUBLIC, true }, + + /* EdDSA Public Key: different key */ + { "example.", 63663, "example2.", 37529, DST_ALG_ED25519, + DST_TYPE_PUBLIC, false }, + + /* DH Keypair: self */ + { "example.", 65316, "example.", 65316, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY, true }, + + /* DH Keypair: different key */ + { "example.", 65316, "example2.", 19823, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY, false }, + + /* DH Keypair: different key (with generator=5) */ + { "example.", 65316, "example3.", 17187, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY, false }, + + /* DH Keypair: different private key */ + { "example.", 65316, "example-private.", 65316, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY, false }, + + /* DH Public Key: self */ + { "example.", 65316, "example.", 65316, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_KEY, true }, + + /* DH Public Key: different key */ + { "example.", 65316, "example2.", 19823, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_KEY, false }, + + /* DH Public Key: different key (with generator=5) */ + { "example.", 65316, "example3.", 17187, DST_ALG_DH, + DST_TYPE_PUBLIC | DST_TYPE_KEY, false }, + }; + unsigned int i; + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + if (!dst_algorithm_supported(testcases[i].alg)) { + continue; + } + + check_cmp(testcases[i].key1_name, testcases[i].key1_id, + testcases[i].key2_name, testcases[i].key2_id, + testcases[i].alg, testcases[i].type, + testcases[i].expect); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(sig_test, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(cmp_test, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/geoip_test.c b/tests/dns/geoip_test.c new file mode 100644 index 0000000..2f5b166 --- /dev/null +++ b/tests/dns/geoip_test.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> +#include <maxminddb.h> + +#include <isc/dir.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <dns/geoip.h> + +#include "geoip2.c" + +#include <tests/dns.h> + +static dns_geoip_databases_t geoip; + +static MMDB_s geoip_country, geoip_city, geoip_as, geoip_isp, geoip_domain; + +static void +load_geoip(const char *dir); +static void +close_geoip(void); + +static int +setup_test(void **state) { + UNUSED(state); + + /* Use databases from the geoip system test */ + load_geoip(TEST_GEOIP_DATA); + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + close_geoip(); + + return (0); +} + +static MMDB_s * +open_geoip2(const char *dir, const char *dbfile, MMDB_s *mmdb) { + char pathbuf[PATH_MAX]; + int ret; + + snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, dbfile); + ret = MMDB_open(pathbuf, MMDB_MODE_MMAP, mmdb); + if (ret == MMDB_SUCCESS) { + return (mmdb); + } + + return (NULL); +} + +static void +load_geoip(const char *dir) { + geoip.country = open_geoip2(dir, "GeoIP2-Country.mmdb", &geoip_country); + geoip.city = open_geoip2(dir, "GeoIP2-City.mmdb", &geoip_city); + geoip.as = open_geoip2(dir, "GeoLite2-ASN.mmdb", &geoip_as); + geoip.isp = open_geoip2(dir, "GeoIP2-ISP.mmdb", &geoip_isp); + geoip.domain = open_geoip2(dir, "GeoIP2-Domain.mmdb", &geoip_domain); +} + +static void +close_geoip(void) { + MMDB_close(&geoip_country); + MMDB_close(&geoip_city); + MMDB_close(&geoip_as); + MMDB_close(&geoip_isp); + MMDB_close(&geoip_domain); +} + +static bool +/* Check if an MMDB entry of a given subtype exists for the given IP */ +entry_exists(dns_geoip_subtype_t subtype, const char *addr) { + struct in6_addr in6; + struct in_addr in4; + isc_netaddr_t na; + MMDB_s *db; + + if (inet_pton(AF_INET6, addr, &in6) == 1) { + isc_netaddr_fromin6(&na, &in6); + } else if (inet_pton(AF_INET, addr, &in4) == 1) { + isc_netaddr_fromin(&na, &in4); + } else { + UNREACHABLE(); + } + + db = geoip2_database(&geoip, fix_subtype(&geoip, subtype)); + + return (db != NULL && get_entry_for(db, &na) != NULL); +} + +/* + * Baseline test - check if get_entry_for() works as expected, i.e. that its + * return values are consistent with the contents of the test MMDBs found in + * bin/tests/system/geoip2/data/ (10.53.0.1 and fd92:7065:b8e:ffff::1 should be + * present in all databases, 192.0.2.128 should only be present in the country + * database, ::1 should be absent from all databases). + */ +ISC_RUN_TEST_IMPL(baseline) { + dns_geoip_subtype_t subtype; + + UNUSED(state); + + subtype = dns_geoip_city_name; + + assert_true(entry_exists(subtype, "10.53.0.1")); + assert_false(entry_exists(subtype, "192.0.2.128")); + assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1")); + assert_false(entry_exists(subtype, "::1")); + + subtype = dns_geoip_country_name; + + assert_true(entry_exists(subtype, "10.53.0.1")); + assert_true(entry_exists(subtype, "192.0.2.128")); + assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1")); + assert_false(entry_exists(subtype, "::1")); + + subtype = dns_geoip_domain_name; + + assert_true(entry_exists(subtype, "10.53.0.1")); + assert_false(entry_exists(subtype, "192.0.2.128")); + assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1")); + assert_false(entry_exists(subtype, "::1")); + + subtype = dns_geoip_isp_name; + + assert_true(entry_exists(subtype, "10.53.0.1")); + assert_false(entry_exists(subtype, "192.0.2.128")); + assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1")); + assert_false(entry_exists(subtype, "::1")); + + subtype = dns_geoip_as_asnum; + + assert_true(entry_exists(subtype, "10.53.0.1")); + assert_false(entry_exists(subtype, "192.0.2.128")); + assert_true(entry_exists(subtype, "fd92:7065:b8e:ffff::1")); + assert_false(entry_exists(subtype, "::1")); +} + +static bool +do_lookup_string(const char *addr, dns_geoip_subtype_t subtype, + const char *string) { + dns_geoip_elem_t elt; + struct in_addr in4; + isc_netaddr_t na; + int n; + + n = inet_pton(AF_INET, addr, &in4); + assert_int_equal(n, 1); + isc_netaddr_fromin(&na, &in4); + + elt.subtype = subtype; + strlcpy(elt.as_string, string, sizeof(elt.as_string)); + + return (dns_geoip_match(&na, &geoip, &elt)); +} + +static bool +do_lookup_string_v6(const char *addr, dns_geoip_subtype_t subtype, + const char *string) { + dns_geoip_elem_t elt; + struct in6_addr in6; + isc_netaddr_t na; + int n; + + n = inet_pton(AF_INET6, addr, &in6); + assert_int_equal(n, 1); + isc_netaddr_fromin6(&na, &in6); + + elt.subtype = subtype; + strlcpy(elt.as_string, string, sizeof(elt.as_string)); + + return (dns_geoip_match(&na, &geoip, &elt)); +} + +/* GeoIP country matching */ +ISC_RUN_TEST_IMPL(country) { + bool match; + + UNUSED(state); + + if (geoip.country == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.1", dns_geoip_country_code, "AU"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_country_name, + "Australia"); + assert_true(match); + + match = do_lookup_string("192.0.2.128", dns_geoip_country_code, "O1"); + assert_true(match); + + match = do_lookup_string("192.0.2.128", dns_geoip_country_name, + "Other"); + assert_true(match); +} + +/* GeoIP country (ipv6) matching */ +ISC_RUN_TEST_IMPL(country_v6) { + bool match; + + UNUSED(state); + + if (geoip.country == NULL) { + skip(); + } + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_country_code, "AU"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_country_name, "Australia"); + assert_true(match); +} + +/* GeoIP city (ipv4) matching */ +ISC_RUN_TEST_IMPL(city) { + bool match; + + UNUSED(state); + + if (geoip.city == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.1", dns_geoip_city_continentcode, + "NA"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_countrycode, "US"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_countryname, + "United States"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_region, "CA"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_regionname, + "California"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_name, + "Redwood City"); + assert_true(match); + + match = do_lookup_string("10.53.0.1", dns_geoip_city_postalcode, + "94063"); + assert_true(match); +} + +/* GeoIP city (ipv6) matching */ +ISC_RUN_TEST_IMPL(city_v6) { + bool match; + + UNUSED(state); + + if (geoip.city == NULL) { + skip(); + } + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_continentcode, "NA"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_countrycode, "US"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_countryname, + "United States"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_region, "CA"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_regionname, "California"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_name, "Redwood City"); + assert_true(match); + + match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", + dns_geoip_city_postalcode, "94063"); + assert_true(match); +} + +/* GeoIP asnum matching */ +ISC_RUN_TEST_IMPL(asnum) { + bool match; + + UNUSED(state); + + if (geoip.as == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.3", dns_geoip_as_asnum, "AS100003"); + assert_true(match); +} + +/* GeoIP isp matching */ +ISC_RUN_TEST_IMPL(isp) { + bool match; + + UNUSED(state); + + if (geoip.isp == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.1", dns_geoip_isp_name, + "One Systems, Inc."); + assert_true(match); +} + +/* GeoIP org matching */ +ISC_RUN_TEST_IMPL(org) { + bool match; + + UNUSED(state); + + if (geoip.as == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.2", dns_geoip_org_name, + "Two Technology Ltd."); + assert_true(match); +} + +/* GeoIP domain matching */ +ISC_RUN_TEST_IMPL(domain) { + bool match; + + UNUSED(state); + + if (geoip.domain == NULL) { + skip(); + } + + match = do_lookup_string("10.53.0.5", dns_geoip_domain_name, "five.es"); + assert_true(match); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(baseline, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(country, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(country_v6, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(city, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(city_v6, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(asnum, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(isp, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(org, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(domain, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/keytable_test.c b/tests/dns/keytable_test.c new file mode 100644 index 0000000..615f90e --- /dev/null +++ b/tests/dns/keytable_test.c @@ -0,0 +1,689 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/md.h> +#include <isc/util.h> + +#include <dns/fixedname.h> +#include <dns/keytable.h> +#include <dns/name.h> +#include <dns/nta.h> +#include <dns/rdataclass.h> +#include <dns/rdatastruct.h> +#include <dns/rootns.h> +#include <dns/view.h> + +#include <dst/dst.h> + +#include <tests/dns.h> + +dns_keytable_t *keytable = NULL; +dns_ntatable_t *ntatable = NULL; + +static const char *keystr1 = "BQEAAAABok+vaUC9neRv8yeT/" + "FEGgN7svR8s7VBUVSBd8NsAiV8AlaAg " + "O5FHar3JQd95i/puZos6Vi6at9/" + "JBbN8qVmO2AuiXxVqfxMKxIcy+LEB " + "0Vw4NaSJ3N3uaVREso6aTSs98H/" + "25MjcwLOr7SFfXA7bGhZatLtYY/xu kp6Km5hMfkE="; + +static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/" + "inaJpYv7vH " + "XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/" + "ItBfh/hL2lm " + "Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi7953" + "2Qeklxh x8pXWdeAaRU="; + +static dns_view_t *view = NULL; + +/* + * Test utilities. In general, these assume input parameters are valid + * (checking with assert_int_equal, thus aborting if not) and unlikely run time + * errors (such as memory allocation failure) won't happen. This helps keep + * the test code concise. + */ + +/* + * Utility to convert C-string to dns_name_t. Return a pointer to + * static data, and so is not thread safe. + */ +static dns_name_t * +str2name(const char *namestr) { + static dns_fixedname_t fname; + static dns_name_t *name; + static isc_buffer_t namebuf; + void *deconst_namestr; + + name = dns_fixedname_initname(&fname); + DE_CONST(namestr, deconst_namestr); /* OK, since we don't modify it */ + isc_buffer_init(&namebuf, deconst_namestr, strlen(deconst_namestr)); + isc_buffer_add(&namebuf, strlen(namestr)); + assert_int_equal( + dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL), + ISC_R_SUCCESS); + + return (name); +} + +static void +create_keystruct(uint16_t flags, uint8_t proto, uint8_t alg, const char *keystr, + dns_rdata_dnskey_t *keystruct) { + unsigned char keydata[4096]; + isc_buffer_t keydatabuf; + isc_region_t r; + const dns_rdataclass_t rdclass = dns_rdataclass_in; + + keystruct->common.rdclass = rdclass; + keystruct->common.rdtype = dns_rdatatype_dnskey; + keystruct->mctx = mctx; + ISC_LINK_INIT(&keystruct->common, link); + keystruct->flags = flags; + keystruct->protocol = proto; + keystruct->algorithm = alg; + + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); + assert_int_equal(isc_base64_decodestring(keystr, &keydatabuf), + ISC_R_SUCCESS); + isc_buffer_usedregion(&keydatabuf, &r); + keystruct->datalen = r.length; + keystruct->data = isc_mem_allocate(mctx, r.length); + memmove(keystruct->data, r.base, r.length); +} + +static void +create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg, + const char *keystr, unsigned char *digest, + dns_rdata_ds_t *dsstruct) { + isc_result_t result; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_dnskey_t dnskey; + + /* + * Populate DNSKEY rdata structure. + */ + create_keystruct(flags, proto, alg, keystr, &dnskey); + + /* + * Convert to wire format. + */ + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + result = dns_rdata_fromstruct(&rdata, dnskey.common.rdclass, + dnskey.common.rdtype, &dnskey, + &rrdatabuf); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Build DS rdata struct. + */ + result = dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, digest, + dsstruct); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_rdata_freestruct(&dnskey); +} + +/* Common setup: create a keytable and ntatable to test with a few keys */ +static void +create_tables(void) { + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); + isc_stdtime_t now; + + assert_int_equal(dns_test_makeview("view", false, &view), + ISC_R_SUCCESS); + + assert_int_equal(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS); + assert_int_equal( + dns_ntatable_create(view, taskmgr, timermgr, &ntatable), + ISC_R_SUCCESS); + + /* Add a normal key */ + dns_test_namefromstring("example.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + + /* Add an initializing managed key */ + dns_test_namefromstring("managed.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + + /* Add a null key */ + assert_int_equal( + dns_keytable_marksecure(keytable, str2name("null.example")), + ISC_R_SUCCESS); + + /* Add a negative trust anchor, duration 1 hour */ + isc_stdtime_get(&now); + assert_int_equal(dns_ntatable_add(ntatable, + str2name("insecure.example"), false, + now, 3600), + ISC_R_SUCCESS); +} + +static void +destroy_tables(void) { + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + if (keytable != NULL) { + dns_keytable_detach(&keytable); + } + + dns_view_detach(&view); +} + +/* add keys to the keytable */ +ISC_RUN_TEST_IMPL(dns_keytable_add) { + dns_keynode_t *keynode = NULL; + dns_keynode_t *null_keynode = NULL; + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); + + UNUSED(state); + + create_tables(); + + /* + * Getting the keynode for the example.com key should succeed. + */ + assert_int_equal( + dns_keytable_find(keytable, str2name("example.com"), &keynode), + ISC_R_SUCCESS); + + /* + * Try to add the same key. This should have no effect but + * report success. + */ + dns_test_namefromstring("example.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &keynode); + assert_int_equal( + dns_keytable_find(keytable, str2name("example.com"), &keynode), + ISC_R_SUCCESS); + + /* Add another key (different keydata) */ + dns_keytable_detachkeynode(keytable, &keynode); + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("example.com"), &keynode), + ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Get the keynode for the managed.com key. Ensure the + * retrieved key is an initializing key, then mark it as trusted using + * dns_keynode_trust() and ensure the latter works as expected. + */ + assert_int_equal( + dns_keytable_find(keytable, str2name("managed.com"), &keynode), + ISC_R_SUCCESS); + assert_int_equal(dns_keynode_initial(keynode), true); + dns_keynode_trust(keynode); + assert_int_equal(dns_keynode_initial(keynode), false); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Add a different managed key for managed.com, marking it as an + * initializing key. Since there is already a trusted key at the + * node, the node should *not* be marked as initializing. + */ + dns_test_namefromstring("managed.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("managed.com"), &keynode), + ISC_R_SUCCESS); + assert_int_equal(dns_keynode_initial(keynode), false); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Add the same managed key again, but this time mark it as a + * non-initializing key. Ensure the previously added key is upgraded + * to a non-initializing key and make sure there are still two key + * nodes for managed.com, both containing non-initializing keys. + */ + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("managed.com"), &keynode), + ISC_R_SUCCESS); + assert_int_equal(dns_keynode_initial(keynode), false); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Add a managed key at a new node, two.com, marking it as an + * initializing key. + */ + dns_test_namefromstring("two.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("two.com"), &keynode), + ISC_R_SUCCESS); + assert_int_equal(dns_keynode_initial(keynode), true); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Add a different managed key for two.com, marking it as a + * non-initializing key. Since there is already an iniitalizing + * trust anchor for two.com and we haven't run dns_keynode_trust(), + * the initialization status should not change. + */ + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("two.com"), &keynode), + ISC_R_SUCCESS); + assert_int_equal(dns_keynode_initial(keynode), true); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * Add a normal key to a name that has a null key. The null key node + * will be updated with the normal key. + */ + assert_int_equal(dns_keytable_find(keytable, str2name("null.example"), + &null_keynode), + ISC_R_SUCCESS); + dns_test_namefromstring("null.example", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_find(keytable, str2name("null.example"), &keynode), + ISC_R_SUCCESS); + assert_ptr_equal(keynode, null_keynode); /* should be the same node */ + dns_keytable_detachkeynode(keytable, &null_keynode); + + /* + * Try to add a null key to a name that already has a key. It's + * effectively no-op, so the same key node is still there. + * (Note: this and above checks confirm that if a name has a null key + * that's the only key for the name). + */ + assert_int_equal( + dns_keytable_marksecure(keytable, str2name("null.example")), + ISC_R_SUCCESS); + assert_int_equal(dns_keytable_find(keytable, str2name("null.example"), + &null_keynode), + ISC_R_SUCCESS); + assert_ptr_equal(keynode, null_keynode); + dns_keytable_detachkeynode(keytable, &null_keynode); + + dns_keytable_detachkeynode(keytable, &keynode); + destroy_tables(); +} + +/* delete keys from the keytable */ +ISC_RUN_TEST_IMPL(dns_keytable_delete) { + create_tables(); + + /* dns_keytable_delete requires exact match */ + assert_int_equal(dns_keytable_delete(keytable, str2name("example.org"), + NULL, NULL), + ISC_R_NOTFOUND); + assert_int_equal(dns_keytable_delete(keytable, + str2name("s.example.com"), NULL, + NULL), + ISC_R_NOTFOUND); + assert_int_equal(dns_keytable_delete(keytable, str2name("example.com"), + NULL, NULL), + ISC_R_SUCCESS); + + /* works also for nodes with a null key */ + assert_int_equal(dns_keytable_delete(keytable, str2name("null.example"), + NULL, NULL), + ISC_R_SUCCESS); + + /* or a negative trust anchor */ + assert_int_equal( + dns_ntatable_delete(ntatable, str2name("insecure.example")), + ISC_R_SUCCESS); + + destroy_tables(); +} + +/* delete key nodes from the keytable */ +ISC_RUN_TEST_IMPL(dns_keytable_deletekey) { + dns_rdata_dnskey_t dnskey; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); + + UNUSED(state); + + create_tables(); + + /* key name doesn't match */ + dns_test_namefromstring("example.org", &fn); + create_keystruct(257, 3, 5, keystr1, &dnskey); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + ISC_R_NOTFOUND); + dns_rdata_freestruct(&dnskey); + + /* subdomain match is the same as no match */ + dns_test_namefromstring("sub.example.org", &fn); + create_keystruct(257, 3, 5, keystr1, &dnskey); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + ISC_R_NOTFOUND); + dns_rdata_freestruct(&dnskey); + + /* name matches but key doesn't match (resulting in PARTIALMATCH) */ + dns_test_namefromstring("example.com", &fn); + create_keystruct(257, 3, 5, keystr2, &dnskey); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + DNS_R_PARTIALMATCH); + dns_rdata_freestruct(&dnskey); + + /* + * exact match: should return SUCCESS on the first try, then + * PARTIALMATCH on the second (because the name existed but + * not a matching key). + */ + create_keystruct(257, 3, 5, keystr1, &dnskey); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + ISC_R_SUCCESS); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + DNS_R_PARTIALMATCH); + + /* + * after deleting the node, any deletekey or delete attempt should + * result in NOTFOUND. + */ + assert_int_equal(dns_keytable_delete(keytable, keyname, NULL, NULL), + ISC_R_SUCCESS); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + ISC_R_NOTFOUND); + dns_rdata_freestruct(&dnskey); + + /* + * A null key node for a name is not deleted when searched by key; + * it must be deleted by dns_keytable_delete() + */ + dns_test_namefromstring("null.example", &fn); + create_keystruct(257, 3, 5, keystr1, &dnskey); + assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), + DNS_R_PARTIALMATCH); + assert_int_equal(dns_keytable_delete(keytable, keyname, NULL, NULL), + ISC_R_SUCCESS); + dns_rdata_freestruct(&dnskey); + + destroy_tables(); +} + +/* check find-variant operations */ +ISC_RUN_TEST_IMPL(dns_keytable_find) { + dns_keynode_t *keynode = NULL; + dns_fixedname_t fname; + dns_name_t *name; + + UNUSED(state); + + create_tables(); + + /* + * dns_keytable_find() requires exact name match. It matches node + * that has a null key, too. + */ + assert_int_equal( + dns_keytable_find(keytable, str2name("example.org"), &keynode), + ISC_R_NOTFOUND); + assert_int_equal(dns_keytable_find(keytable, + str2name("sub.example.com"), + &keynode), + ISC_R_NOTFOUND); + assert_int_equal( + dns_keytable_find(keytable, str2name("example.com"), &keynode), + ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &keynode); + assert_int_equal( + dns_keytable_find(keytable, str2name("null.example"), &keynode), + ISC_R_SUCCESS); + dns_keytable_detachkeynode(keytable, &keynode); + + /* + * dns_keytable_finddeepestmatch() allows partial match. Also match + * nodes with a null key. + */ + name = dns_fixedname_initname(&fname); + assert_int_equal(dns_keytable_finddeepestmatch( + keytable, str2name("example.com"), name), + ISC_R_SUCCESS); + assert_true(dns_name_equal(name, str2name("example.com"))); + assert_int_equal(dns_keytable_finddeepestmatch( + keytable, str2name("s.example.com"), name), + ISC_R_SUCCESS); + assert_true(dns_name_equal(name, str2name("example.com"))); + assert_int_equal(dns_keytable_finddeepestmatch( + keytable, str2name("example.org"), name), + ISC_R_NOTFOUND); + assert_int_equal(dns_keytable_finddeepestmatch( + keytable, str2name("null.example"), name), + ISC_R_SUCCESS); + assert_true(dns_name_equal(name, str2name("null.example"))); + + destroy_tables(); +} + +/* check issecuredomain() */ +ISC_RUN_TEST_IMPL(dns_keytable_issecuredomain) { + bool issecure; + const char **n; + const char *names[] = { "example.com", "sub.example.com", + "null.example", "sub.null.example", NULL }; + + UNUSED(state); + create_tables(); + + /* + * Domains that are an exact or partial match of a key name are + * considered secure. It's the case even if the key is null + * (validation will then fail, but that's actually the intended effect + * of installing a null key). + */ + for (n = names; *n != NULL; n++) { + assert_int_equal(dns_keytable_issecuredomain(keytable, + str2name(*n), NULL, + &issecure), + ISC_R_SUCCESS); + assert_true(issecure); + } + + /* + * If the key table has no entry (not even a null one) for a domain or + * any of its ancestors, that domain is considered insecure. + */ + assert_int_equal(dns_keytable_issecuredomain(keytable, + str2name("example.org"), + NULL, &issecure), + ISC_R_SUCCESS); + assert_false(issecure); + + destroy_tables(); +} + +/* check dns_keytable_dump() */ +ISC_RUN_TEST_IMPL(dns_keytable_dump) { + FILE *f = fopen("/dev/null", "w"); + + UNUSED(state); + + create_tables(); + + /* + * Right now, we only confirm the dump attempt doesn't cause disruption + * (so we don't check the dump content). + */ + assert_int_equal(dns_keytable_dump(keytable, f), ISC_R_SUCCESS); + fclose(f); + + destroy_tables(); +} + +/* check negative trust anchors */ +ISC_RUN_TEST_IMPL(dns_keytable_nta) { + isc_result_t result; + bool issecure, covered; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + dns_view_t *myview = NULL; + isc_stdtime_t now; + + UNUSED(state); + + result = dns_test_makeview("view", false, &myview); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_create(taskmgr, 0, &myview->task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_view_initsecroots(myview, mctx); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_view_getsecroots(myview, &keytable); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_view_initntatable(myview, taskmgr, timermgr); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_view_getntatable(myview, &ntatable); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_test_namefromstring("example", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + result = dns_keytable_add(keytable, false, false, keyname, &ds, NULL, + NULL), + assert_int_equal(result, ISC_R_SUCCESS); + + isc_stdtime_get(&now); + result = dns_ntatable_add(ntatable, str2name("insecure.example"), false, + now, 1); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Should be secure */ + result = dns_view_issecuredomain(myview, + str2name("test.secure.example"), now, + true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_false(covered); + assert_true(issecure); + + /* Should not be secure */ + result = dns_view_issecuredomain(myview, + str2name("test.insecure.example"), now, + true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(covered); + assert_false(issecure); + + /* NTA covered */ + covered = dns_view_ntacovers(myview, now, str2name("insecure.example"), + dns_rootname); + assert_true(covered); + + /* Not NTA covered */ + covered = dns_view_ntacovers(myview, now, str2name("secure.example"), + dns_rootname); + assert_false(covered); + + /* As of now + 2, the NTA should be clear */ + result = dns_view_issecuredomain(myview, + str2name("test.insecure.example"), + now + 2, true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_false(covered); + assert_true(issecure); + + /* Now check deletion */ + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_false(covered); + assert_true(issecure); + + result = dns_ntatable_add(ntatable, str2name("new.example"), false, now, + 3600); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(covered); + assert_false(issecure); + + result = dns_ntatable_delete(ntatable, str2name("new.example")); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_view_issecuredomain(myview, str2name("test.new.example"), + now, true, &covered, &issecure); + assert_int_equal(result, ISC_R_SUCCESS); + assert_false(covered); + assert_true(issecure); + + /* Clean up */ + dns_ntatable_detach(&ntatable); + dns_keytable_detach(&keytable); + dns_view_detach(&myview); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_keytable_add, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_delete, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_deletekey, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_find, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_issecuredomain, setup_managers, + teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_dump, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_keytable_nta, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/master_test.c b/tests/dns/master_test.c new file mode 100644 index 0000000..eaebddd --- /dev/null +++ b/tests/dns/master_test.c @@ -0,0 +1,582 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/dir.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/cache.h> +#include <dns/callbacks.h> +#include <dns/db.h> +#include <dns/master.h> +#include <dns/masterdump.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> + +#include <tests/dns.h> + +static void +nullmsg(dns_rdatacallbacks_t *cb, const char *fmt, ...) { + UNUSED(cb); + UNUSED(fmt); +} + +#define BUFLEN 255 +#define BIGBUFLEN (70 * 1024) +#define TEST_ORIGIN "test" + +static dns_masterrawheader_t header; +static bool headerset; + +dns_name_t dns_origin; +char origin[sizeof(TEST_ORIGIN)]; +unsigned char name_buf[BUFLEN]; +dns_rdatacallbacks_t callbacks; +char *include_file = NULL; + +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header); + +static isc_result_t +add_callback(void *arg, const dns_name_t *owner, dns_rdataset_t *dataset) { + char buf[BIGBUFLEN]; + isc_buffer_t target; + isc_result_t result; + + UNUSED(arg); + + isc_buffer_init(&target, buf, BIGBUFLEN); + result = dns_rdataset_totext(dataset, owner, false, false, &target); + return (result); +} + +static void +rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *h) { + UNUSED(zone); + header = *h; + headerset = true; +} + +static isc_result_t +setup_master(void (*warn)(struct dns_rdatacallbacks *, const char *, ...), + void (*error)(struct dns_rdatacallbacks *, const char *, ...)) { + isc_result_t result; + int len; + isc_buffer_t source; + isc_buffer_t target; + + strlcpy(origin, TEST_ORIGIN, sizeof(origin)); + len = strlen(origin); + isc_buffer_init(&source, origin, len); + isc_buffer_add(&source, len); + isc_buffer_setactive(&source, len); + isc_buffer_init(&target, name_buf, BUFLEN); + dns_name_init(&dns_origin, NULL); + dns_master_initrawheader(&header); + + result = dns_name_fromtext(&dns_origin, &source, dns_rootname, 0, + &target); + if (result != ISC_R_SUCCESS) { + return (result); + } + + dns_rdatacallbacks_init_stdio(&callbacks); + callbacks.add = add_callback; + callbacks.rawdata = rawdata_callback; + callbacks.zone = NULL; + if (warn != NULL) { + callbacks.warn = warn; + } + if (error != NULL) { + callbacks.error = error; + } + headerset = false; + return (result); +} + +static isc_result_t +test_master(const char *workdir, const char *testfile, + dns_masterformat_t format, + void (*warn)(struct dns_rdatacallbacks *, const char *, ...), + void (*error)(struct dns_rdatacallbacks *, const char *, ...)) { + isc_result_t result; + + result = setup_master(warn, error); + if (result != ISC_R_SUCCESS) { + return (result); + } + + dns_rdatacallbacks_init_stdio(&callbacks); + callbacks.add = add_callback; + callbacks.rawdata = rawdata_callback; + callbacks.zone = NULL; + if (warn != NULL) { + callbacks.warn = warn; + } + if (error != NULL) { + callbacks.error = error; + } + + if (workdir != NULL) { + result = isc_dir_chdir(workdir); + if (result != ISC_R_SUCCESS) { + return (result); + } + } + + result = dns_master_loadfile(testfile, &dns_origin, &dns_origin, + dns_rdataclass_in, true, 0, &callbacks, + NULL, NULL, mctx, format, 0); + + return (result); +} + +static void +include_callback(const char *filename, void *arg) { + char **argp = (char **)arg; + *argp = isc_mem_strdup(mctx, filename); +} + +/* + * Successful load test: + * dns_master_loadfile() loads a valid master file and returns success + */ +ISC_RUN_TEST_IMPL(load) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master1.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * Unexpected end of file test: + * dns_master_loadfile() returns DNS_R_UNEXPECTED when file ends too soon + */ +ISC_RUN_TEST_IMPL(unexpected) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master2.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_UNEXPECTEDEND); +} + +/* + * No owner test: + * dns_master_loadfile() accepts broken zones with no TTL for first record + * if it is an SOA + */ +ISC_RUN_TEST_IMPL(noowner) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master3.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, DNS_R_NOOWNER); +} + +/* + * No TTL test: + * dns_master_loadfile() returns DNS_R_NOOWNER when no owner name is + * specified + */ +ISC_RUN_TEST_IMPL(nottl) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master4.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * Bad class test: + * dns_master_loadfile() returns DNS_R_BADCLASS when record class doesn't + * match zone class + */ +ISC_RUN_TEST_IMPL(badclass) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master5.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, DNS_R_BADCLASS); +} + +/* + * Too big rdata test: + * dns_master_loadfile() returns ISC_R_NOSPACE when record is too big + */ +ISC_RUN_TEST_IMPL(toobig) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master15.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_NOSPACE); +} + +/* + * Maximum rdata test: + * dns_master_loadfile() returns ISC_R_SUCCESS when record is maximum size + */ +ISC_RUN_TEST_IMPL(maxrdata) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master16.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * DNSKEY test: + * dns_master_loadfile() understands DNSKEY with key material + */ +ISC_RUN_TEST_IMPL(dnskey) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master6.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * DNSKEY with no key material test: + * dns_master_loadfile() understands DNSKEY with no key material + * + * RFC 4034 removed the ability to signal NOKEY, so empty key material should + * be rejected. + */ +ISC_RUN_TEST_IMPL(dnsnokey) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master7.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_UNEXPECTEDEND); +} + +/* + * Include test: + * dns_master_loadfile() understands $INCLUDE + */ +ISC_RUN_TEST_IMPL(include) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master8.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, DNS_R_SEENINCLUDE); +} + +/* + * Include file list test: + * dns_master_loadfile4() returns names of included file + */ +ISC_RUN_TEST_IMPL(master_includelist) { + isc_result_t result; + char *filename = NULL; + + UNUSED(state); + + result = setup_master(nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_dir_chdir(SRCDIR); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_master_loadfile( + TESTS_DIR "/testdata/master/master8.data", &dns_origin, + &dns_origin, dns_rdataclass_in, 0, true, &callbacks, + include_callback, &filename, mctx, dns_masterformat_text, 0); + assert_int_equal(result, DNS_R_SEENINCLUDE); + assert_non_null(filename); + if (filename != NULL) { + assert_string_equal(filename, "testdata/master/master6.data"); + isc_mem_free(mctx, filename); + } +} + +/* + * Include failure test: + * dns_master_loadfile() understands $INCLUDE failures + */ +ISC_RUN_TEST_IMPL(includefail) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master9.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, DNS_R_BADCLASS); +} + +/* + * Non-empty blank lines test: + * dns_master_loadfile() handles non-empty blank lines + */ +ISC_RUN_TEST_IMPL(blanklines) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master10.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * SOA leading zeroes test: + * dns_master_loadfile() allows leading zeroes in SOA + */ + +ISC_RUN_TEST_IMPL(leadingzero) { + isc_result_t result; + + UNUSED(state); + + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master11.data", + dns_masterformat_text, nullmsg, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* masterfile totext tests */ +ISC_RUN_TEST_IMPL(totext) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + isc_buffer_t target; + unsigned char buf[BIGBUFLEN]; + + UNUSED(state); + + /* First, test with an empty rdataset */ + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = dns_rdataclass_in; + rdatalist.type = dns_rdatatype_none; + rdatalist.covers = dns_rdatatype_none; + + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&target, buf, BIGBUFLEN); + result = dns_master_rdatasettotext(dns_rootname, &rdataset, + &dns_master_style_debug, NULL, + &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_buffer_usedlength(&target), 0); + + /* + * XXX: We will also need to add tests for dumping various + * rdata types, classes, etc, and comparing the results against + * known-good output. + */ +} + +/* + * Raw load test: + * dns_master_loadfile() loads a valid raw file and returns success + */ +ISC_RUN_TEST_IMPL(loadraw) { + isc_result_t result; + + UNUSED(state); + + /* Raw format version 0 */ + result = test_master(BUILDDIR, "testdata/master/master12.data", + dns_masterformat_raw, nullmsg, nullmsg); + assert_string_equal(isc_result_totext(result), "success"); + assert_true(headerset); + assert_int_equal(header.flags, 0); + + /* Raw format version 1, no source serial */ + result = test_master(BUILDDIR, "testdata/master/master13.data", + dns_masterformat_raw, nullmsg, nullmsg); + assert_string_equal(isc_result_totext(result), "success"); + assert_true(headerset); + assert_int_equal(header.flags, 0); + + /* Raw format version 1, source serial == 2011120101 */ + result = test_master(BUILDDIR, "testdata/master/master14.data", + dns_masterformat_raw, nullmsg, nullmsg); + assert_string_equal(isc_result_totext(result), "success"); + assert_true(headerset); + assert_true((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + assert_int_equal(header.sourceserial, 2011120101); +} + +/* + * Raw dump test: + * dns_master_dump*() functions dump valid raw files + */ +ISC_RUN_TEST_IMPL(dumpraw) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbversion_t *version = NULL; + char myorigin[sizeof(TEST_ORIGIN)]; + dns_name_t dnsorigin; + isc_buffer_t source, target; + unsigned char namebuf[BUFLEN]; + int len; + + UNUSED(state); + + strlcpy(myorigin, TEST_ORIGIN, sizeof(myorigin)); + len = strlen(myorigin); + isc_buffer_init(&source, myorigin, len); + isc_buffer_add(&source, len); + isc_buffer_setactive(&source, len); + isc_buffer_init(&target, namebuf, BUFLEN); + dns_name_init(&dnsorigin, NULL); + result = dns_name_fromtext(&dnsorigin, &source, dns_rootname, 0, + &target); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_create(mctx, "rbt", &dnsorigin, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_dir_chdir(SRCDIR); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_db_load(db, TESTS_DIR "/testdata/master/master1.data", + dns_masterformat_text, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_dir_chdir(BUILDDIR); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_db_currentversion(db, &version); + + result = dns_master_dump(mctx, db, version, &dns_master_style_default, + "test.dump", dns_masterformat_raw, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = test_master(NULL, "test.dump", dns_masterformat_raw, nullmsg, + nullmsg); + assert_string_equal(isc_result_totext(result), "success"); + assert_true(headerset); + assert_int_equal(header.flags, 0); + + dns_master_initrawheader(&header); + header.sourceserial = 12345; + header.flags |= DNS_MASTERRAW_SOURCESERIALSET; + + unlink("test.dump"); + result = dns_master_dump(mctx, db, version, &dns_master_style_default, + "test.dump", dns_masterformat_raw, &header); + assert_int_equal(result, ISC_R_SUCCESS); + + result = test_master(NULL, "test.dump", dns_masterformat_raw, nullmsg, + nullmsg); + assert_string_equal(isc_result_totext(result), "success"); + assert_true(headerset); + assert_true((header.flags & DNS_MASTERRAW_SOURCESERIALSET) != 0); + assert_int_equal(header.sourceserial, 12345); + + unlink("test.dump"); + dns_db_closeversion(db, &version, false); + dns_db_detach(&db); +} + +static const char *warn_expect_value; +static bool warn_expect_result; + +static void +warn_expect(struct dns_rdatacallbacks *mycallbacks, const char *fmt, ...) { + char buf[4096]; + va_list ap; + + UNUSED(mycallbacks); + + warn_expect_result = false; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + if (warn_expect_value != NULL && strstr(buf, warn_expect_value) != NULL) + { + warn_expect_result = true; + } +} + +/* + * Origin change test: + * dns_master_loadfile() rejects zones with inherited name following $ORIGIN + */ +ISC_RUN_TEST_IMPL(neworigin) { + isc_result_t result; + + UNUSED(state); + + warn_expect_value = "record with inherited owner"; + result = test_master(SRCDIR, TESTS_DIR "/testdata/master/master17.data", + dns_masterformat_text, warn_expect, nullmsg); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(warn_expect_result); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(load) +ISC_TEST_ENTRY(unexpected) +ISC_TEST_ENTRY(noowner) +ISC_TEST_ENTRY(nottl) +ISC_TEST_ENTRY(badclass) +ISC_TEST_ENTRY(dnskey) +ISC_TEST_ENTRY(dnsnokey) +ISC_TEST_ENTRY(include) +ISC_TEST_ENTRY(master_includelist) +ISC_TEST_ENTRY(includefail) +ISC_TEST_ENTRY(blanklines) +ISC_TEST_ENTRY(leadingzero) +ISC_TEST_ENTRY(totext) +ISC_TEST_ENTRY(loadraw) +ISC_TEST_ENTRY(dumpraw) +ISC_TEST_ENTRY(toobig) +ISC_TEST_ENTRY(maxrdata) +ISC_TEST_ENTRY(neworigin) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/mkraw.pl b/tests/dns/mkraw.pl new file mode 100644 index 0000000..5e0db75 --- /dev/null +++ b/tests/dns/mkraw.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Convert a hexdump to binary format. +# +# To convert binary data to the input format for this command, +# use the following: +# +# perl -e 'while (read(STDIN, my $byte, 1)) { +# print unpack("H2", $byte); +# } +# print "\n";' < file > file.in + +use strict; +chomp(my $line = <STDIN>); +print pack("H*", $line); diff --git a/tests/dns/name_test.c b/tests/dns/name_test.c new file mode 100644 index 0000000..511ee3c --- /dev/null +++ b/tests/dns/name_test.c @@ -0,0 +1,731 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/thread.h> +#include <isc/util.h> + +#include <dns/compress.h> +#include <dns/fixedname.h> +#include <dns/name.h> + +#include <tests/dns.h> + +/* Set to true (or use -v option) for verbose output */ +static bool verbose = false; + +/* dns_name_fullcompare test */ +ISC_RUN_TEST_IMPL(fullcompare) { + dns_fixedname_t fixed1; + dns_fixedname_t fixed2; + dns_name_t *name1; + dns_name_t *name2; + dns_namereln_t relation; + int i; + isc_result_t result; + struct { + const char *name1; + const char *name2; + dns_namereln_t relation; + int order; + unsigned int nlabels; + } data[] = { + /* relative */ + { "", "", dns_namereln_equal, 0, 0 }, + { "foo", "", dns_namereln_subdomain, 1, 0 }, + { "", "foo", dns_namereln_contains, -1, 0 }, + { "foo", "bar", dns_namereln_none, 4, 0 }, + { "bar", "foo", dns_namereln_none, -4, 0 }, + { "bar.foo", "foo", dns_namereln_subdomain, 1, 1 }, + { "foo", "bar.foo", dns_namereln_contains, -1, 1 }, + { "baz.bar.foo", "bar.foo", dns_namereln_subdomain, 1, 2 }, + { "bar.foo", "baz.bar.foo", dns_namereln_contains, -1, 2 }, + { "foo.example", "bar.example", dns_namereln_commonancestor, 4, + 1 }, + + /* absolute */ + { ".", ".", dns_namereln_equal, 0, 1 }, + { "foo.", "bar.", dns_namereln_commonancestor, 4, 1 }, + { "bar.", "foo.", dns_namereln_commonancestor, -4, 1 }, + { "foo.example.", "bar.example.", dns_namereln_commonancestor, + 4, 2 }, + { "bar.foo.", "foo.", dns_namereln_subdomain, 1, 2 }, + { "foo.", "bar.foo.", dns_namereln_contains, -1, 2 }, + { "baz.bar.foo.", "bar.foo.", dns_namereln_subdomain, 1, 3 }, + { "bar.foo.", "baz.bar.foo.", dns_namereln_contains, -1, 3 }, + { NULL, NULL, dns_namereln_none, 0, 0 } + }; + + UNUSED(state); + + name1 = dns_fixedname_initname(&fixed1); + name2 = dns_fixedname_initname(&fixed2); + for (i = 0; data[i].name1 != NULL; i++) { + int order = 3000; + unsigned int nlabels = 3000; + + if (data[i].name1[0] == 0) { + dns_fixedname_init(&fixed1); + } else { + result = dns_name_fromstring2(name1, data[i].name1, + NULL, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + } + if (data[i].name2[0] == 0) { + dns_fixedname_init(&fixed2); + } else { + result = dns_name_fromstring2(name2, data[i].name2, + NULL, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + } + relation = dns_name_fullcompare(name1, name1, &order, &nlabels); + assert_int_equal(relation, dns_namereln_equal); + assert_int_equal(order, 0); + assert_int_equal(nlabels, name1->labels); + + /* Some random initializer */ + order = 3001; + nlabels = 3001; + + relation = dns_name_fullcompare(name1, name2, &order, &nlabels); + assert_int_equal(relation, data[i].relation); + assert_int_equal(order, data[i].order); + assert_int_equal(nlabels, data[i].nlabels); + } +} + +static void +compress_test(dns_name_t *name1, dns_name_t *name2, dns_name_t *name3, + unsigned char *expected, unsigned int length, + dns_compress_t *cctx, dns_decompress_t *dctx) { + isc_buffer_t source; + isc_buffer_t target; + dns_name_t name; + unsigned char buf1[1024]; + unsigned char buf2[1024]; + + isc_buffer_init(&source, buf1, sizeof(buf1)); + isc_buffer_init(&target, buf2, sizeof(buf2)); + + assert_int_equal(dns_name_towire(name1, cctx, &source), ISC_R_SUCCESS); + + assert_int_equal(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS); + assert_int_equal(dns_name_towire(name2, cctx, &source), ISC_R_SUCCESS); + assert_int_equal(dns_name_towire(name3, cctx, &source), ISC_R_SUCCESS); + + isc_buffer_setactive(&source, source.used); + + dns_name_init(&name, NULL); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) == + ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) == + ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) == + ISC_R_SUCCESS); + RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) == + ISC_R_SUCCESS); + dns_decompress_invalidate(dctx); + + assert_int_equal(target.used, length); + assert_true(memcmp(target.base, expected, target.used) == 0); +} + +/* name compression test */ +ISC_RUN_TEST_IMPL(compression) { + unsigned int allowed; + dns_compress_t cctx; + dns_decompress_t dctx; + dns_name_t name1; + dns_name_t name2; + dns_name_t name3; + isc_region_t r; + unsigned char plain1[] = "\003yyy\003foo"; + unsigned char plain2[] = "\003bar\003yyy\003foo"; + unsigned char plain3[] = "\003xxx\003bar\003foo"; + unsigned char plain[] = "\003yyy\003foo\0\003bar\003yyy\003foo\0\003" + "bar\003yyy\003foo\0\003xxx\003bar\003foo"; + + UNUSED(state); + + dns_name_init(&name1, NULL); + r.base = plain1; + r.length = sizeof(plain1); + dns_name_fromregion(&name1, &r); + + dns_name_init(&name2, NULL); + r.base = plain2; + r.length = sizeof(plain2); + dns_name_fromregion(&name2, &r); + + dns_name_init(&name3, NULL); + r.base = plain3; + r.length = sizeof(plain3); + dns_name_fromregion(&name3, &r); + + /* Test 1: NONE */ + allowed = DNS_COMPRESS_NONE; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test2: GLOBAL14 */ + allowed = DNS_COMPRESS_GLOBAL14; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test3: ALL */ + allowed = DNS_COMPRESS_ALL; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test4: NONE disabled */ + allowed = DNS_COMPRESS_NONE; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test5: GLOBAL14 disabled */ + allowed = DNS_COMPRESS_GLOBAL14; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); + + /* Test6: ALL disabled */ + allowed = DNS_COMPRESS_ALL; + assert_int_equal(dns_compress_init(&cctx, -1, mctx), ISC_R_SUCCESS); + dns_compress_setmethods(&cctx, allowed); + dns_compress_disable(&cctx); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, allowed); + + compress_test(&name1, &name2, &name3, plain, sizeof(plain), &cctx, + &dctx); + + dns_compress_rollback(&cctx, 0); + dns_compress_invalidate(&cctx); +} + +/* is trust-anchor-telemetry test */ +ISC_RUN_TEST_IMPL(istat) { + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + size_t i; + struct { + const char *name; + bool istat; + } data[] = { { ".", false }, + { "_ta-", false }, + { "_ta-1234", true }, + { "_TA-1234", true }, + { "+TA-1234", false }, + { "_fa-1234", false }, + { "_td-1234", false }, + { "_ta_1234", false }, + { "_ta-g234", false }, + { "_ta-1h34", false }, + { "_ta-12i4", false }, + { "_ta-123j", false }, + { "_ta-1234-abcf", true }, + { "_ta-1234-abcf-ED89", true }, + { "_ta-12345-abcf-ED89", false }, + { "_ta-.example", false }, + { "_ta-1234.example", true }, + { "_ta-1234-abcf.example", true }, + { "_ta-1234-abcf-ED89.example", true }, + { "_ta-12345-abcf-ED89.example", false }, + { "_ta-1234-abcfe-ED89.example", false }, + { "_ta-1234-abcf-EcD89.example", false } }; + + UNUSED(state); + + name = dns_fixedname_initname(&fixed); + + for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { + result = dns_name_fromstring(name, data[i].name, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(dns_name_istat(name), data[i].istat); + } +} + +/* dns_nane_init */ +ISC_RUN_TEST_IMPL(init) { + dns_name_t name; + unsigned char offsets[1]; + + UNUSED(state); + + dns_name_init(&name, offsets); + + assert_null(name.ndata); + assert_int_equal(name.length, 0); + assert_int_equal(name.labels, 0); + assert_int_equal(name.attributes, 0); + assert_ptr_equal(name.offsets, offsets); + assert_null(name.buffer); +} + +/* dns_nane_invalidate */ +ISC_RUN_TEST_IMPL(invalidate) { + dns_name_t name; + unsigned char offsets[1]; + + UNUSED(state); + + dns_name_init(&name, offsets); + dns_name_invalidate(&name); + + assert_null(name.ndata); + assert_int_equal(name.length, 0); + assert_int_equal(name.labels, 0); + assert_int_equal(name.attributes, 0); + assert_null(name.offsets); + assert_null(name.buffer); +} + +/* dns_nane_setbuffer/hasbuffer */ +ISC_RUN_TEST_IMPL(buffer) { + dns_name_t name; + unsigned char buf[BUFSIZ]; + isc_buffer_t b; + + UNUSED(state); + + isc_buffer_init(&b, buf, BUFSIZ); + dns_name_init(&name, NULL); + dns_name_setbuffer(&name, &b); + assert_ptr_equal(name.buffer, &b); + assert_true(dns_name_hasbuffer(&name)); +} + +/* dns_nane_isabsolute */ +ISC_RUN_TEST_IMPL(isabsolute) { + struct { + const char *namestr; + bool expect; + } testcases[] = { { "x", false }, + { "a.b.c.d.", true }, + { "x.z", false } }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_name_t name; + unsigned char data[BUFSIZ]; + isc_buffer_t b, nb; + size_t len; + + len = strlen(testcases[i].namestr); + isc_buffer_constinit(&b, testcases[i].namestr, len); + isc_buffer_add(&b, len); + + dns_name_init(&name, NULL); + isc_buffer_init(&nb, data, BUFSIZ); + dns_name_setbuffer(&name, &nb); + result = dns_name_fromtext(&name, &b, NULL, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_int_equal(dns_name_isabsolute(&name), + testcases[i].expect); + } +} + +/* dns_nane_hash */ +ISC_RUN_TEST_IMPL(hash) { + struct { + const char *name1; + const char *name2; + bool expect; + bool expecti; + } testcases[] = { + { "a.b.c.d", "A.B.C.D", true, false }, + { "a.b.c.d.", "A.B.C.D.", true, false }, + { "a.b.c.d", "a.b.c.d", true, true }, + { "A.B.C.D.", "A.B.C.D.", true, false }, + { "x.y.z.w", "a.b.c.d", false, false }, + { "x.y.z.w.", "a.b.c.d.", false, false }, + }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + unsigned int h1, h2; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Check case-insensitive hashing first */ + h1 = dns_name_hash(n1, false); + h2 = dns_name_hash(n2, false); + + if (verbose) { + print_message("# %s hashes to %u, " + "%s to %u, case insensitive\n", + testcases[i].name1, h1, + testcases[i].name2, h2); + } + + assert_int_equal((h1 == h2), testcases[i].expect); + + /* Now case-sensitive */ + h1 = dns_name_hash(n1, false); + h2 = dns_name_hash(n2, false); + + if (verbose) { + print_message("# %s hashes to %u, " + "%s to %u, case sensitive\n", + testcases[i].name1, h1, + testcases[i].name2, h2); + } + + assert_int_equal((h1 == h2), testcases[i].expect); + } +} + +/* dns_nane_issubdomain */ +ISC_RUN_TEST_IMPL(issubdomain) { + struct { + const char *name1; + const char *name2; + bool expect; + } testcases[] = { + { "c.d", "a.b.c.d", false }, { "c.d.", "a.b.c.d.", false }, + { "b.c.d", "c.d", true }, { "a.b.c.d.", "c.d.", true }, + { "a.b.c", "a.b.c", true }, { "a.b.c.", "a.b.c.", true }, + { "x.y.z", "a.b.c", false } + }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + if (verbose) { + print_message("# check: %s %s a subdomain of %s\n", + testcases[i].name1, + testcases[i].expect ? "is" : "is not", + testcases[i].name2); + } + + assert_int_equal(dns_name_issubdomain(n1, n2), + testcases[i].expect); + } +} + +/* dns_nane_countlabels */ +ISC_RUN_TEST_IMPL(countlabels) { + struct { + const char *namestr; + unsigned int expect; + } testcases[] = { + { "c.d", 2 }, { "c.d.", 3 }, { "a.b.c.d.", 5 }, + { "a.b.c.d", 4 }, { "a.b.c", 3 }, { ".", 1 }, + }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t fname; + dns_name_t *name; + + name = dns_fixedname_initname(&fname); + + result = dns_name_fromstring2(name, testcases[i].namestr, NULL, + 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + if (verbose) { + print_message("# %s: expect %u labels\n", + testcases[i].namestr, + testcases[i].expect); + } + + assert_int_equal(dns_name_countlabels(name), + testcases[i].expect); + } +} + +/* dns_nane_getlabel */ +ISC_RUN_TEST_IMPL(getlabel) { + struct { + const char *name1; + unsigned int pos1; + const char *name2; + unsigned int pos2; + } testcases[] = { + { "c.d", 1, "a.b.c.d", 3 }, + { "a.b.c.d", 3, "c.d", 1 }, + { "a.b.c.", 3, "A.B.C.", 3 }, + }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + dns_label_t l1, l2; + unsigned int j; + + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_name_getlabel(n1, testcases[i].pos1, &l1); + dns_name_getlabel(n2, testcases[i].pos2, &l2); + assert_int_equal(l1.length, l2.length); + + for (j = 0; j < l1.length; j++) { + assert_int_equal(l1.base[j], l2.base[j]); + } + } +} + +/* dns_nane_getlabelsequence */ +ISC_RUN_TEST_IMPL(getlabelsequence) { + struct { + const char *name1; + unsigned int pos1; + const char *name2; + unsigned int pos2; + unsigned int range; + } testcases[] = { + { "c.d", 1, "a.b.c.d", 3, 1 }, + { "a.b.c.d.e", 2, "c.d", 0, 2 }, + { "a.b.c", 0, "a.b.c", 0, 3 }, + }; + unsigned int i; + + UNUSED(state); + + for (i = 0; i < (sizeof(testcases) / sizeof(testcases[0])); i++) { + isc_result_t result; + dns_name_t t1, t2; + dns_fixedname_t f1, f2; + dns_name_t *n1, *n2; + + /* target names */ + dns_name_init(&t1, NULL); + dns_name_init(&t2, NULL); + + /* source names */ + n1 = dns_fixedname_initname(&f1); + n2 = dns_fixedname_initname(&f2); + + result = dns_name_fromstring2(n1, testcases[i].name1, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_name_fromstring2(n2, testcases[i].name2, NULL, 0, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_name_getlabelsequence(n1, testcases[i].pos1, + testcases[i].range, &t1); + dns_name_getlabelsequence(n2, testcases[i].pos2, + testcases[i].range, &t2); + + assert_true(dns_name_equal(&t1, &t2)); + } +} + +#ifdef DNS_BENCHMARK_TESTS + +/* + * XXXMUKS: Don't delete this code. It is useful in benchmarking the + * name parser, but we don't require it as part of the unit test runs. + */ + +/* Benchmark dns_name_fromwire() implementation */ + +ISC_RUN_TEST_IMPL(fromwire_thread(void *arg) { + unsigned int maxval = 32000000; + uint8_t data[] = { 3, 'w', 'w', 'w', 7, 'e', 'x', + 'a', 'm', 'p', 'l', 'e', 7, 'i', + 'n', 'v', 'a', 'l', 'i', 'd', 0 }; + unsigned char output_data[DNS_NAME_MAXWIRE]; + isc_buffer_t source, target; + unsigned int i; + dns_decompress_t dctx; + + UNUSED(arg); + + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); + dns_decompress_setmethods(&dctx, DNS_COMPRESS_NONE); + + isc_buffer_init(&source, data, sizeof(data)); + isc_buffer_add(&source, sizeof(data)); + isc_buffer_init(&target, output_data, sizeof(output_data)); + + /* Parse 32 million names in each thread */ + for (i = 0; i < maxval; i++) { + dns_name_t name; + + isc_buffer_clear(&source); + isc_buffer_clear(&target); + isc_buffer_add(&source, sizeof(data)); + isc_buffer_setactive(&source, sizeof(data)); + + dns_name_init(&name, NULL); + (void)dns_name_fromwire(&name, &source, &dctx, 0, &target); + } + + return (NULL); +} + +ISC_RUN_TEST_IMPL(benchmark) { + isc_result_t result; + unsigned int i; + isc_time_t ts1, ts2; + double t; + unsigned int nthreads; + isc_thread_t threads[32]; + + UNUSED(state); + + debug_mem_record = false; + + result = isc_time_now(&ts1); + assert_int_equal(result, ISC_R_SUCCESS); + + nthreads = ISC_MIN(isc_os_ncpus(), 32); + nthreads = ISC_MAX(nthreads, 1); + for (i = 0; i < nthreads; i++) { + isc_thread_create(fromwire_thread, NULL, &threads[i]); + } + + for (i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + result = isc_time_now(&ts2); + assert_int_equal(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("%u dns_name_fromwire() calls, %f seconds, %f calls/second\n", + nthreads * 32000000, t / 1000000.0, + (nthreads * 32000000) / (t / 1000000.0)); +} + +#endif /* DNS_BENCHMARK_TESTS */ + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(fullcompare) +ISC_TEST_ENTRY(compression) +ISC_TEST_ENTRY(istat) +ISC_TEST_ENTRY(init) +ISC_TEST_ENTRY(invalidate) +ISC_TEST_ENTRY(buffer) +ISC_TEST_ENTRY(isabsolute) +ISC_TEST_ENTRY(hash) +ISC_TEST_ENTRY(issubdomain) +ISC_TEST_ENTRY(countlabels) +ISC_TEST_ENTRY(getlabel) +ISC_TEST_ENTRY(getlabelsequence) +#ifdef DNS_BENCHMARK_TESTS +ISC_TEST_ENTRY(benchmark) +#endif /* DNS_BENCHMARK_TESTS */ +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/nsec3_test.c b/tests/dns/nsec3_test.c new file mode 100644 index 0000000..c2fcacd --- /dev/null +++ b/tests/dns/nsec3_test.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/nsec3.h> + +#include <tests/dns.h> + +static void +iteration_test(const char *file, unsigned int expected) { + isc_result_t result; + dns_db_t *db = NULL; + unsigned int iterations; + + result = dns_test_loaddb(&db, dns_dbtype_zone, "test", file); + assert_int_equal(result, ISC_R_SUCCESS); + + iterations = dns_nsec3_maxiterations(); + + assert_int_equal(iterations, expected); + + dns_db_detach(&db); +} + +/*% + * Structure containing parameters for nsec3param_salttotext_test(). + */ +typedef struct { + const char *nsec3param_text; /* NSEC3PARAM RDATA in text form */ + const char *expected_salt; /* string expected in target buffer */ +} nsec3param_salttotext_test_params_t; + +/*% + * Check whether dns_nsec3param_salttotext() handles supplied text form + * NSEC3PARAM RDATA correctly: test whether the result of calling the former is + * as expected and whether it properly checks available buffer space. + * + * Assumes supplied text form NSEC3PARAM RDATA is valid as testing handling of + * invalid NSEC3PARAM RDATA is out of scope of this unit test. + */ +static void +nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t *params) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3param_t nsec3param; + unsigned char buf[1024]; + isc_result_t result; + char salt[64]; + size_t length; + + /* + * Prepare a dns_rdata_nsec3param_t structure for testing. + */ + result = dns_test_rdatafromstring( + &rdata, dns_rdataclass_in, dns_rdatatype_nsec3param, buf, + sizeof(buf), params->nsec3param_text, false); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Check typical use. + */ + result = dns_nsec3param_salttotext(&nsec3param, salt, sizeof(salt)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(salt, params->expected_salt); + + /* + * Ensure available space in the buffer is checked before the salt is + * printed to it and that the amount of space checked for includes the + * terminating NULL byte. + */ + length = strlen(params->expected_salt); + assert_true(length < sizeof(salt) - 1); /* prevent buffer overwrite */ + assert_true(length > 0U); /* prevent length underflow */ + + result = dns_nsec3param_salttotext(&nsec3param, salt, length - 1); + assert_int_equal(result, ISC_R_NOSPACE); + + result = dns_nsec3param_salttotext(&nsec3param, salt, length); + assert_int_equal(result, ISC_R_NOSPACE); + + result = dns_nsec3param_salttotext(&nsec3param, salt, length + 1); + assert_int_equal(result, ISC_R_SUCCESS); +} + +/* + * check that appropriate max iterations is returned for different + * key size mixes + */ +ISC_RUN_TEST_IMPL(max_iterations) { + UNUSED(state); + + iteration_test(TESTS_DIR "/testdata/nsec3/1024.db", 150); + iteration_test(TESTS_DIR "/testdata/nsec3/2048.db", 150); + iteration_test(TESTS_DIR "/testdata/nsec3/4096.db", 150); + iteration_test(TESTS_DIR "/testdata/nsec3/min-1024.db", 150); + iteration_test(TESTS_DIR "/testdata/nsec3/min-2048.db", 150); +} + +/* check dns_nsec3param_salttotext() */ +ISC_RUN_TEST_IMPL(nsec3param_salttotext) { + size_t i; + + const nsec3param_salttotext_test_params_t tests[] = { + /* + * Tests with non-empty salts. + */ + { "0 0 10 0123456789abcdef", "0123456789ABCDEF" }, + { "0 1 11 0123456789abcdef", "0123456789ABCDEF" }, + { "1 0 12 42", "42" }, + { "1 1 13 42", "42" }, + /* + * Test with empty salt. + */ + { "0 0 0 -", "-" }, + }; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + nsec3param_salttotext_test(&tests[i]); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(max_iterations) +ISC_TEST_ENTRY(nsec3param_salttotext) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/nsec3param_test.c b/tests/dns/nsec3param_test.c new file mode 100644 index 0000000..50c8b85 --- /dev/null +++ b/tests/dns/nsec3param_test.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/hex.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/nsec3.h> + +#include "zone_p.h" + +#include <tests/dns.h> + +#define HASH 1 +#define FLAGS 0 +#define ITER 5 +#define SALTLEN 4 +#define SALT "FEDCBA98" + +/*% + * Structures containing parameters for nsec3param_salttotext_test(). + */ +typedef struct { + dns_hash_t hash; + unsigned char flags; + dns_iterations_t iterations; + unsigned char salt_length; + const char *salt; +} nsec3param_rdata_test_params_t; + +typedef struct { + nsec3param_rdata_test_params_t lookup; + nsec3param_rdata_test_params_t expect; + bool resalt; + isc_result_t expected_result; +} nsec3param_change_test_params_t; + +static void +decode_salt(const char *string, unsigned char *salt, size_t saltlen) { + isc_buffer_t buf; + isc_result_t result; + + isc_buffer_init(&buf, salt, saltlen); + result = isc_hex_decodestring(string, &buf); + assert_int_equal(result, ISC_R_SUCCESS); +} + +static void +copy_params(nsec3param_rdata_test_params_t from, dns_rdata_nsec3param_t *to, + unsigned char *saltbuf, size_t saltlen) { + to->hash = from.hash; + to->flags = from.flags; + to->iterations = from.iterations; + to->salt_length = from.salt_length; + if (from.salt == NULL) { + to->salt = NULL; + } else if (strcmp(from.salt, "-") == 0) { + DE_CONST("-", to->salt); + } else { + decode_salt(from.salt, saltbuf, saltlen); + to->salt = saltbuf; + } +} + +static nsec3param_rdata_test_params_t +rdata_fromparams(uint8_t hash, uint8_t flags, uint16_t iter, uint8_t saltlen, + const char *salt) { + nsec3param_rdata_test_params_t nsec3param; + nsec3param.hash = hash; + nsec3param.flags = flags; + nsec3param.iterations = iter; + nsec3param.salt_length = saltlen; + nsec3param.salt = salt; + return (nsec3param); +} + +/*% + * Check whether zone_lookup_nsec3param() finds the correct NSEC3PARAM + * and sets the correct parameters to use in dns_zone_setnsec3param(). + */ +static void +nsec3param_change_test(const nsec3param_change_test_params_t *test) { + dns_zone_t *zone = NULL; + dns_rdata_nsec3param_t param, lookup, expect; + isc_result_t result; + unsigned char lookupsalt[255]; + unsigned char expectsalt[255]; + unsigned char saltbuf[255]; + + /* + * Prepare a zone along with its signing keys. + */ + result = dns_test_makezone("nsec3", &zone, NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zone_setfile( + zone, TESTS_DIR "/testdata/nsec3param/nsec3.db.signed", + dns_masterformat_text, &dns_master_style_default); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zone_load(zone, false); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Copy parameters. + */ + copy_params(test->lookup, &lookup, lookupsalt, sizeof(lookupsalt)); + copy_params(test->expect, &expect, expectsalt, sizeof(expectsalt)); + + /* + * Test dns__zone_lookup_nsec3param(). + */ + result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m, saltbuf, + test->resalt); + assert_int_equal(result, test->expected_result); + assert_int_equal(param.hash, expect.hash); + assert_int_equal(param.flags, expect.flags); + assert_int_equal(param.iterations, expect.iterations); + assert_int_equal(param.salt_length, expect.salt_length); + assert_non_null(param.salt); + if (expect.salt != NULL) { + int ret = memcmp(param.salt, expect.salt, expect.salt_length); + assert_true(ret == 0); + } else { + /* + * We don't know what the new salt is, but we can compare it + * to the previous salt and test that it has changed. + */ + unsigned char salt[SALTLEN]; + int ret; + decode_salt(SALT, salt, SALTLEN); + ret = memcmp(param.salt, salt, SALTLEN); + assert_false(ret == 0); + } + + /* + * Detach. + */ + dns_zone_detach(&zone); +} + +ISC_RUN_TEST_IMPL(nsec3param_change) { + size_t i; + + /* + * Define tests. + */ + const nsec3param_change_test_params_t tests[] = { + /* + * 1. Change nothing (don't care about salt). + * This should return ISC_R_SUCCESS because we are already + * using these NSEC3 parameters. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false, + ISC_R_SUCCESS }, + /* + * 2. Change nothing, but force a resalt. + * This should change the salt. Set 'expect.salt' to NULL to + * test a new salt has been generated. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true, + DNS_R_NSEC3RESALT }, + /* + * 3. Change iterations. + * The NSEC3 paarameters are not found, and there is no + * need to resalt because an explicit salt has been set, + * and resalt is not enforced. + */ + { rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), false, + ISC_R_NOTFOUND }, + /* + * 4. Change iterations, don't care about the salt. + * We don't care about the salt. Since we need to change the + * NSEC3 parameters, we will also resalt. + */ + { rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), false, + DNS_R_NSEC3RESALT }, + /* + * 5. Change salt length. + * Changing salt length means we need to resalt. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), + rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), false, + DNS_R_NSEC3RESALT }, + /* + * 6. Set explicit salt. + * A different salt, so the NSEC3 parameters are not found. + * No need to resalt because an explicit salt is available. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), + rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), false, + ISC_R_NOTFOUND }, + /* + * 7. Same salt. + * Nothing changed, so expect ISC_R_SUCCESS as a result. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false, + ISC_R_SUCCESS }, + /* + * 8. Same salt, and force resalt. + * Nothing changed, but a resalt is enforced. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true, + DNS_R_NSEC3RESALT }, + /* + * 9. No salt. + * Change parameters to use no salt. These parameters are + * not found, and no new salt needs to be generated. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 0, NULL), + rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true, + ISC_R_NOTFOUND }, + /* + * 10. No salt, explicit. + * Same as above, but set no salt explicitly. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), + rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true, + ISC_R_NOTFOUND }, + }; + + UNUSED(state); + + /* + * Run tests. + */ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + nsec3param_change_test(&tests[i]); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(nsec3param_change) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/private_test.c b/tests/dns/private_test.c new file mode 100644 index 0000000..9f3a87f --- /dev/null +++ b/tests/dns/private_test.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/util.h> + +#include <dns/nsec3.h> +#include <dns/private.h> +#include <dns/rdataclass.h> +#include <dns/rdatatype.h> + +#include <dst/dst.h> + +#include <tests/dns.h> + +static dns_rdatatype_t privatetype = 65534; + +static int +setup_test(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dst_lib_init(mctx, NULL); + + if (result != ISC_R_SUCCESS) { + return (1); + } + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +typedef struct { + unsigned char alg; + dns_keytag_t keyid; + bool remove; + bool complete; +} signing_testcase_t; + +typedef struct { + unsigned char hash; + unsigned char flags; + unsigned int iterations; + unsigned long salt; + bool remove; + bool pending; + bool nonsec; +} nsec3_testcase_t; + +static void +make_signing(signing_testcase_t *testcase, dns_rdata_t *private, + unsigned char *buf, size_t len) { + dns_rdata_init(private); + + buf[0] = testcase->alg; + buf[1] = (testcase->keyid & 0xff00) >> 8; + buf[2] = (testcase->keyid & 0xff); + buf[3] = testcase->remove; + buf[4] = testcase->complete; + private->data = buf; + private->length = len; + private->type = privatetype; + private->rdclass = dns_rdataclass_in; +} + +static void +make_nsec3(nsec3_testcase_t *testcase, dns_rdata_t *private, + unsigned char *pbuf) { + dns_rdata_nsec3param_t params; + dns_rdata_t nsec3param = DNS_RDATA_INIT; + unsigned char bufdata[BUFSIZ]; + isc_buffer_t buf; + uint32_t salt; + unsigned char *sp; + int slen = 4; + + /* for simplicity, we're using a maximum salt length of 4 */ + salt = htonl(testcase->salt); + sp = (unsigned char *)&salt; + while (slen > 0 && *sp == '\0') { + slen--; + sp++; + } + + params.common.rdclass = dns_rdataclass_in; + params.common.rdtype = dns_rdatatype_nsec3param; + params.hash = testcase->hash; + params.iterations = testcase->iterations; + params.salt = sp; + params.salt_length = slen; + + params.flags = testcase->flags; + if (testcase->remove) { + params.flags |= DNS_NSEC3FLAG_REMOVE; + if (testcase->nonsec) { + params.flags |= DNS_NSEC3FLAG_NONSEC; + } + } else { + params.flags |= DNS_NSEC3FLAG_CREATE; + if (testcase->pending) { + params.flags |= DNS_NSEC3FLAG_INITIAL; + } + } + + isc_buffer_init(&buf, bufdata, sizeof(bufdata)); + dns_rdata_fromstruct(&nsec3param, dns_rdataclass_in, + dns_rdatatype_nsec3param, ¶ms, &buf); + + dns_rdata_init(private); + + dns_nsec3param_toprivate(&nsec3param, private, privatetype, pbuf, + DNS_NSEC3PARAM_BUFFERSIZE + 1); +} + +/* convert private signing records to text */ +ISC_RUN_TEST_IMPL(private_signing_totext) { + dns_rdata_t private; + int i; + + signing_testcase_t testcases[] = { { DST_ALG_RSASHA512, 12345, 0, 0 }, + { DST_ALG_RSASHA256, 54321, 1, 0 }, + { DST_ALG_NSEC3RSASHA1, 22222, 0, + 1 }, + { DST_ALG_RSASHA1, 33333, 1, 1 } }; + const char *results[] = { "Signing with key 12345/RSASHA512", + "Removing signatures for key 54321/RSASHA256", + "Done signing with key 22222/NSEC3RSASHA1", + ("Done removing signatures for key " + "33333/RSASHA1") }; + int ncases = 4; + + UNUSED(state); + + for (i = 0; i < ncases; i++) { + unsigned char data[5]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_signing(&testcases[i], &private, data, sizeof(data)); + dns_private_totext(&private, &buf); + assert_string_equal(output, results[i]); + } +} + +/* convert private chain records to text */ +ISC_RUN_TEST_IMPL(private_nsec3_totext) { + dns_rdata_t private; + int i; + + nsec3_testcase_t testcases[] = { + { 1, 0, 1, 0xbeef, 0, 0, 0 }, + { 1, 1, 10, 0xdadd, 0, 0, 0 }, + { 1, 0, 20, 0xbead, 0, 1, 0 }, + { 1, 0, 30, 0xdeaf, 1, 0, 0 }, + { 1, 0, 100, 0xfeedabee, 1, 0, 1 }, + }; + const char *results[] = { "Creating NSEC3 chain 1 0 1 BEEF", + "Creating NSEC3 chain 1 1 10 DADD", + "Pending NSEC3 chain 1 0 20 BEAD", + ("Removing NSEC3 chain 1 0 30 DEAF / " + "creating NSEC chain"), + "Removing NSEC3 chain 1 0 100 FEEDABEE" }; + int ncases = 5; + + UNUSED(state); + + for (i = 0; i < ncases; i++) { + unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_nsec3(&testcases[i], &private, data); + dns_private_totext(&private, &buf); + assert_string_equal(output, results[i]); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(private_signing_totext, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(private_nsec3_totext, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rbt_test.c b/tests/dns/rbt_test.c new file mode 100644 index 0000000..c66c365 --- /dev/null +++ b/tests/dns/rbt_test.c @@ -0,0 +1,1300 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <ctype.h> +#include <fcntl.h> +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/result.h> +#include <isc/stdio.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/thread.h> +#include <isc/time.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/compress.h> +#include <dns/fixedname.h> +#include <dns/log.h> +#include <dns/name.h> +#include <dns/rbt.h> + +#include <dst/dst.h> + +#include <tests/dns.h> + +typedef struct { + dns_rbt_t *rbt; + dns_rbt_t *rbt_distances; +} test_context_t; + +/* The initial structure of domain tree will be as follows: + * + * . + * | + * b + * / \ + * a d.e.f + * / | \ + * c | g.h + * | | + * w.y i + * / | \ \ + * x | z k + * | | + * p j + * / \ + * o q + */ + +/* The full absolute names of the nodes in the tree (the tree also + * contains "." which is not included in this list). + */ +static const char *const domain_names[] = { + "c", "b", "a", "x.d.e.f", + "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f", + "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h" +}; + +static const size_t domain_names_count = + (sizeof(domain_names) / sizeof(domain_names[0])); + +/* These are set as the node data for the tree used in distances check + * (for the names in domain_names[] above). + */ +static const int node_distances[] = { 3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2 }; + +/* + * The domain order should be: + * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f, + * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h + * . (no data, can't be found) + * | + * b + * / \ + * a d.e.f + * / | \ + * c | g.h + * | | + * w.y i + * / | \ \ + * x | z k + * | | + * p j + * / \ + * o q + */ + +static const char *const ordered_names[] = { + "a", "b", "c", "d.e.f", "x.d.e.f", + "w.y.d.e.f", "o.w.y.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", + "j.z.d.e.f", "g.h", "i.g.h", "k.g.h" +}; + +static const size_t ordered_names_count = + (sizeof(ordered_names) / sizeof(*ordered_names)); + +static void +delete_data(void *data, void *arg) { + UNUSED(arg); + + isc_mem_put(mctx, data, sizeof(size_t)); +} + +static test_context_t * +test_context_setup(void) { + test_context_t *ctx; + isc_result_t result; + size_t i; + + ctx = isc_mem_get(mctx, sizeof(*ctx)); + assert_non_null(ctx); + + ctx->rbt = NULL; + result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt); + assert_int_equal(result, ISC_R_SUCCESS); + + ctx->rbt_distances = NULL; + result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt_distances); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < domain_names_count; i++) { + size_t *n; + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(domain_names[i], &fname); + + name = dns_fixedname_name(&fname); + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = i + 1; + result = dns_rbt_addname(ctx->rbt, name, n); + assert_int_equal(result, ISC_R_SUCCESS); + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = node_distances[i]; + result = dns_rbt_addname(ctx->rbt_distances, name, n); + assert_int_equal(result, ISC_R_SUCCESS); + } + + return (ctx); +} + +static void +test_context_teardown(test_context_t *ctx) { + dns_rbt_destroy(&ctx->rbt); + dns_rbt_destroy(&ctx->rbt_distances); + + isc_mem_put(mctx, ctx, sizeof(*ctx)); +} + +/* + * Walk the tree and ensure that all the test nodes are present. + */ +static void +check_test_data(dns_rbt_t *rbt) { + dns_fixedname_t fixed; + isc_result_t result; + dns_name_t *foundname; + size_t i; + + foundname = dns_fixedname_initname(&fixed); + + for (i = 0; i < domain_names_count; i++) { + dns_fixedname_t fname; + dns_name_t *name; + size_t *n; + + dns_test_namefromstring(domain_names[i], &fname); + + name = dns_fixedname_name(&fname); + n = NULL; + result = dns_rbt_findname(rbt, name, 0, foundname, (void *)&n); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(*n, i + 1); + } +} + +/* Test the creation of an rbt */ +ISC_RUN_TEST_IMPL(rbt_create) { + test_context_t *ctx; + bool tree_ok; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + check_test_data(ctx->rbt); + + tree_ok = dns__rbt_checkproperties(ctx->rbt); + assert_true(tree_ok); + + test_context_teardown(ctx); +} + +/* Test dns_rbt_nodecount() on a tree */ +ISC_RUN_TEST_IMPL(rbt_nodecount) { + test_context_t *ctx; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + assert_int_equal(15, dns_rbt_nodecount(ctx->rbt)); + + test_context_teardown(ctx); +} + +/* Test dns_rbtnode_get_distance() on a tree */ +ISC_RUN_TEST_IMPL(rbtnode_get_distance) { + isc_result_t result; + test_context_t *ctx; + const char *name_str = "a"; + dns_fixedname_t fname; + dns_name_t *name; + dns_rbtnode_t *node = NULL; + dns_rbtnodechain_t chain; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + dns_test_namefromstring(name_str, &fname); + name = dns_fixedname_name(&fname); + + dns_rbtnodechain_init(&chain); + + result = dns_rbt_findnode(ctx->rbt_distances, name, NULL, &node, &chain, + 0, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + while (node != NULL) { + const size_t *distance = (const size_t *)node->data; + if (distance != NULL) { + assert_int_equal(*distance, + dns__rbtnode_getdistance(node)); + } + result = dns_rbtnodechain_next(&chain, NULL, NULL); + if (result == ISC_R_NOMORE) { + break; + } + dns_rbtnodechain_current(&chain, NULL, NULL, &node); + } + + assert_int_equal(result, ISC_R_NOMORE); + + dns_rbtnodechain_invalidate(&chain); + + test_context_teardown(ctx); +} + +/* + * Test tree balance, inserting names in random order. + * + * This test checks an important performance-related property of + * the red-black tree, which is important for us: the longest + * path from a sub-tree's root to a node is no more than + * 2log(n). This check verifies that the tree is balanced. + */ +ISC_RUN_TEST_IMPL(rbt_check_distance_random) { + dns_rbt_t *mytree = NULL; + const unsigned int log_num_nodes = 16; + isc_result_t result; + bool tree_ok; + int i; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Names are inserted in random order. */ + + /* Make a large 65536 node top-level domain tree, i.e., the + * following code inserts names such as: + * + * savoucnsrkrqzpkqypbygwoiliawpbmz. + * wkadamcbbpjtundbxcmuayuycposvngx. + * wzbpznemtooxdpjecdxynsfztvnuyfao. + * yueojmhyffslpvfmgyfwioxegfhepnqq. + */ + for (i = 0; i < (1 << log_num_nodes); i++) { + size_t *n; + char namebuf[34]; + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = i + 1; + + while (1) { + int j; + dns_fixedname_t fname; + dns_name_t *name; + + for (j = 0; j < 32; j++) { + uint32_t v = isc_random_uniform(26); + namebuf[j] = 'a' + v; + } + namebuf[32] = '.'; + namebuf[33] = 0; + + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_addname(mytree, name, n); + if (result == ISC_R_SUCCESS) { + break; + } + } + } + + /* 1 (root . node) + (1 << log_num_nodes) */ + assert_int_equal(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree)); + + /* The distance from each node to its sub-tree root must be less + * than 2 * log(n). + */ + assert_true((2U * log_num_nodes) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + assert_true(tree_ok); + + dns_rbt_destroy(&mytree); +} + +/* + * Test tree balance, inserting names in sorted order. + * + * This test checks an important performance-related property of + * the red-black tree, which is important for us: the longest + * path from a sub-tree's root to a node is no more than + * 2log(n). This check verifies that the tree is balanced. + */ +ISC_RUN_TEST_IMPL(rbt_check_distance_ordered) { + dns_rbt_t *mytree = NULL; + const unsigned int log_num_nodes = 16; + isc_result_t result; + bool tree_ok; + int i; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Names are inserted in sorted order. */ + + /* Make a large 65536 node top-level domain tree, i.e., the + * following code inserts names such as: + * + * name00000000. + * name00000001. + * name00000002. + * name00000003. + */ + for (i = 0; i < (1 << log_num_nodes); i++) { + size_t *n; + char namebuf[14]; + dns_fixedname_t fname; + dns_name_t *name; + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = i + 1; + + snprintf(namebuf, sizeof(namebuf), "name%08x.", i); + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_addname(mytree, name, n); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* 1 (root . node) + (1 << log_num_nodes) */ + assert_int_equal(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree)); + + /* The distance from each node to its sub-tree root must be less + * than 2 * log(n). + */ + assert_true((2U * log_num_nodes) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + assert_true(tree_ok); + + dns_rbt_destroy(&mytree); +} + +static isc_result_t +insert_helper(dns_rbt_t *rbt, const char *namestr, dns_rbtnode_t **node) { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(namestr, &fname); + name = dns_fixedname_name(&fname); + + return (dns_rbt_addnode(rbt, name, node)); +} + +static bool +compare_labelsequences(dns_rbtnode_t *node, const char *labelstr) { + dns_name_t name; + isc_result_t result; + char *nodestr = NULL; + bool is_equal; + + dns_name_init(&name, NULL); + dns_rbt_namefromnode(node, &name); + + result = dns_name_tostring(&name, &nodestr, mctx); + assert_int_equal(result, ISC_R_SUCCESS); + + is_equal = strcmp(labelstr, nodestr) == 0 ? true : false; + + isc_mem_free(mctx, nodestr); + + return (is_equal); +} + +/* Test insertion into a tree */ +ISC_RUN_TEST_IMPL(rbt_insert) { + isc_result_t result; + test_context_t *ctx; + dns_rbtnode_t *node; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + /* Check node count before beginning. */ + assert_int_equal(15, dns_rbt_nodecount(ctx->rbt)); + + /* Try to insert a node that already exists. */ + node = NULL; + result = insert_helper(ctx->rbt, "d.e.f", &node); + assert_int_equal(result, ISC_R_EXISTS); + + /* Node count must not have changed. */ + assert_int_equal(15, dns_rbt_nodecount(ctx->rbt)); + + /* Try to insert a node that doesn't exist. */ + node = NULL; + result = insert_helper(ctx->rbt, "0", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "0")); + + /* Node count must have increased. */ + assert_int_equal(16, dns_rbt_nodecount(ctx->rbt)); + + /* Another. */ + node = NULL; + result = insert_helper(ctx->rbt, "example.com", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(node); + assert_null(node->data); + + /* Node count must have increased. */ + assert_int_equal(17, dns_rbt_nodecount(ctx->rbt)); + + /* Re-adding it should return EXISTS */ + node = NULL; + result = insert_helper(ctx->rbt, "example.com", &node); + assert_int_equal(result, ISC_R_EXISTS); + + /* Node count must not have changed. */ + assert_int_equal(17, dns_rbt_nodecount(ctx->rbt)); + + /* Fission the node d.e.f */ + node = NULL; + result = insert_helper(ctx->rbt, "k.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "k")); + + /* Node count must have incremented twice ("d.e.f" fissioned to + * "d" and "e.f", and the newly added "k"). + */ + assert_int_equal(19, dns_rbt_nodecount(ctx->rbt)); + + /* Fission the node "g.h" */ + node = NULL; + result = insert_helper(ctx->rbt, "h", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "h")); + + /* Node count must have incremented ("g.h" fissioned to "g" and + * "h"). + */ + assert_int_equal(20, dns_rbt_nodecount(ctx->rbt)); + + /* Add child domains */ + + node = NULL; + result = insert_helper(ctx->rbt, "m.p.w.y.d.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "m")); + assert_int_equal(21, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "n.p.w.y.d.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "n")); + assert_int_equal(22, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "l.a", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(compare_labelsequences(node, "l")); + assert_int_equal(23, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "r.d.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + node = NULL; + result = insert_helper(ctx->rbt, "s.d.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(25, dns_rbt_nodecount(ctx->rbt)); + + node = NULL; + result = insert_helper(ctx->rbt, "h.w.y.d.e.f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Add more nodes one by one to cover left and right rotation + * functions. + */ + node = NULL; + result = insert_helper(ctx->rbt, "f", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "m", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "nm", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "om", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "k", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "l", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "fe", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "ge", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "i", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "ae", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + node = NULL; + result = insert_helper(ctx->rbt, "n", &node); + assert_int_equal(result, ISC_R_SUCCESS); + + test_context_teardown(ctx); +} + +/* + * Test removal from a tree + * + * This testcase checks that after node removal, the binary-search tree is + * valid and all nodes that are supposed to exist are present in the + * correct order. It mainly tests DomainTree as a BST, and not particularly + * as a red-black tree. This test checks node deletion when upper nodes + * have data. + */ +ISC_RUN_TEST_IMPL(rbt_remove) { + isc_result_t result; + size_t j; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + /* + * Delete single nodes and check if the rest of the nodes exist. + */ + for (j = 0; j < ordered_names_count; j++) { + dns_rbt_t *mytree = NULL; + dns_rbtnode_t *node; + size_t i; + size_t *n; + bool tree_ok; + dns_rbtnodechain_t chain; + size_t start_node; + + /* Create a tree. */ + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Insert test data into the tree. */ + for (i = 0; i < domain_names_count; i++) { + node = NULL; + result = insert_helper(mytree, domain_names[i], &node); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* Check that all names exist in order. */ + for (i = 0; i < ordered_names_count; i++) { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[i], &fname); + + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, &node, + NULL, DNS_RBTFIND_EMPTYDATA, + NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Add node data */ + assert_non_null(node); + assert_null(node->data); + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = i; + + node->data = n; + } + + /* Now, delete the j'th node from the tree. */ + { + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[j], &fname); + + name = dns_fixedname_name(&fname); + + result = dns_rbt_deletename(mytree, name, false); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* Check RB tree properties. */ + tree_ok = dns__rbt_checkproperties(mytree); + assert_true(tree_ok); + + dns_rbtnodechain_init(&chain); + + /* Now, walk through nodes in order. */ + if (j == 0) { + /* + * Node for ordered_names[0] was already deleted + * above. We start from node 1. + */ + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[0], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, &node, + NULL, 0, NULL, NULL); + assert_int_equal(result, ISC_R_NOTFOUND); + + dns_test_namefromstring(ordered_names[1], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, &node, + &chain, 0, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + start_node = 1; + } else { + /* Start from node 0. */ + dns_fixedname_t fname; + dns_name_t *name; + + dns_test_namefromstring(ordered_names[0], &fname); + name = dns_fixedname_name(&fname); + node = NULL; + result = dns_rbt_findnode(mytree, name, NULL, &node, + &chain, 0, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + start_node = 0; + } + + /* + * node and chain have been set by the code above at + * this point. + */ + for (i = start_node; i < ordered_names_count; i++) { + dns_fixedname_t fname_j, fname_i; + dns_name_t *name_j, *name_i; + + dns_test_namefromstring(ordered_names[j], &fname_j); + name_j = dns_fixedname_name(&fname_j); + dns_test_namefromstring(ordered_names[i], &fname_i); + name_i = dns_fixedname_name(&fname_i); + + if (dns_name_equal(name_i, name_j)) { + /* + * This may be true for the last node if + * we seek ahead in the loop using + * dns_rbtnodechain_next() below. + */ + if (node == NULL) { + break; + } + + /* All ordered nodes have data + * initially. If any node is empty, it + * means it was removed, but an empty + * node exists because it is a + * super-domain. Just skip it. + */ + if (node->data == NULL) { + result = dns_rbtnodechain_next( + &chain, NULL, NULL); + if (result == ISC_R_NOMORE) { + node = NULL; + } else { + dns_rbtnodechain_current( + &chain, NULL, NULL, + &node); + } + } + continue; + } + + assert_non_null(node); + + n = (size_t *)node->data; + if (n != NULL) { + /* printf("n=%zu, i=%zu\n", *n, i); */ + assert_int_equal(*n, i); + } + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + if (result == ISC_R_NOMORE) { + node = NULL; + } else { + dns_rbtnodechain_current(&chain, NULL, NULL, + &node); + } + } + + /* We should have reached the end of the tree. */ + assert_null(node); + + dns_rbt_destroy(&mytree); + } +} + +static void +insert_nodes(dns_rbt_t *mytree, char **names, size_t *names_count, + uint32_t num_names) { + uint32_t i; + dns_rbtnode_t *node; + + for (i = 0; i < num_names; i++) { + size_t *n; + char namebuf[34]; + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + + *n = i; /* Unused value */ + + while (1) { + int j; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + for (j = 0; j < 32; j++) { + uint32_t v = isc_random_uniform(26); + namebuf[j] = 'a' + v; + } + namebuf[32] = '.'; + namebuf[33] = 0; + + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + node = NULL; + result = dns_rbt_addnode(mytree, name, &node); + if (result == ISC_R_SUCCESS) { + node->data = n; + names[*names_count] = isc_mem_strdup(mctx, + namebuf); + assert_non_null(names[*names_count]); + *names_count += 1; + break; + } + } + } +} + +static void +remove_nodes(dns_rbt_t *mytree, char **names, size_t *names_count, + uint32_t num_names) { + uint32_t i; + + UNUSED(mytree); + + for (i = 0; i < num_names; i++) { + uint32_t node; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + node = isc_random_uniform(*names_count); + + dns_test_namefromstring(names[node], &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_deletename(mytree, name, false); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_mem_free(mctx, names[node]); + if (*names_count > 0) { + names[node] = names[*names_count - 1]; + names[*names_count - 1] = NULL; + *names_count -= 1; + } + } +} + +static void +check_tree(dns_rbt_t *mytree, char **names, size_t names_count) { + bool tree_ok; + + UNUSED(names); + + assert_int_equal(names_count + 1, dns_rbt_nodecount(mytree)); + + /* + * The distance from each node to its sub-tree root must be less + * than 2 * log_2(1024). + */ + assert_true((2 * 10) >= dns__rbt_getheight(mytree)); + + /* Also check RB tree properties */ + tree_ok = dns__rbt_checkproperties(mytree); + assert_true(tree_ok); +} + +/* + * Test insert and remove in a loop. + * + * What is the best way to test our red-black tree code? It is + * not a good method to test every case handled in the actual + * code itself. This is because our approach itself may be + * incorrect. + * + * We test our code at the interface level here by exercising the + * tree randomly multiple times, checking that red-black tree + * properties are valid, and all the nodes that are supposed to be + * in the tree exist and are in order. + * + * NOTE: These tests are run within a single tree level in the + * forest. The number of nodes in the tree level doesn't grow + * over 1024. + */ +ISC_RUN_TEST_IMPL(rbt_insert_and_remove) { + isc_result_t result; + dns_rbt_t *mytree = NULL; + size_t *n; + char *names[1024]; + size_t names_count; + int i; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + result = dns_rbt_create(mctx, delete_data, NULL, &mytree); + assert_int_equal(result, ISC_R_SUCCESS); + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + result = dns_rbt_addname(mytree, dns_rootname, n); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(names, 0, sizeof(names)); + names_count = 0; + + /* Repeat the insert/remove test some 4096 times */ + for (i = 0; i < 4096; i++) { + uint32_t num_names; + + if (names_count < 1024) { + num_names = isc_random_uniform(1024 - names_count); + num_names++; + } else { + num_names = 0; + } + + insert_nodes(mytree, names, &names_count, num_names); + check_tree(mytree, names, names_count); + + if (names_count > 0) { + num_names = isc_random_uniform(names_count); + num_names++; + } else { + num_names = 0; + } + + remove_nodes(mytree, names, &names_count, num_names); + check_tree(mytree, names, names_count); + } + + /* Remove the rest of the nodes */ + remove_nodes(mytree, names, &names_count, names_count); + check_tree(mytree, names, names_count); + + for (i = 0; i < 1024; i++) { + if (names[i] != NULL) { + isc_mem_free(mctx, names[i]); + } + } + + result = dns_rbt_deletename(mytree, dns_rootname, false); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(dns_rbt_nodecount(mytree), 0); + + dns_rbt_destroy(&mytree); +} + +/* Test findname return values */ +ISC_RUN_TEST_IMPL(rbt_findname) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname, found; + dns_name_t *name = NULL, *foundname = NULL; + size_t *n = NULL; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + /* Try to find a name that exists. */ + dns_test_namefromstring("d.e.f", &fname); + name = dns_fixedname_name(&fname); + + foundname = dns_fixedname_initname(&found); + + result = dns_rbt_findname(ctx->rbt, name, DNS_RBTFIND_EMPTYDATA, + foundname, (void *)&n); + assert_true(dns_name_equal(foundname, name)); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Now without EMPTYDATA */ + result = dns_rbt_findname(ctx->rbt, name, 0, foundname, (void *)&n); + assert_int_equal(result, ISC_R_NOTFOUND); + + /* Now one that partially matches */ + dns_test_namefromstring("d.e.f.g.h.i.j", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_findname(ctx->rbt, name, DNS_RBTFIND_EMPTYDATA, + foundname, (void *)&n); + assert_int_equal(result, DNS_R_PARTIALMATCH); + + /* Now one that doesn't match */ + dns_test_namefromstring("1.2", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_findname(ctx->rbt, name, DNS_RBTFIND_EMPTYDATA, + foundname, (void *)&n); + assert_int_equal(result, DNS_R_PARTIALMATCH); + assert_true(dns_name_equal(foundname, dns_rootname)); + + test_context_teardown(ctx); +} + +/* Test addname return values */ +ISC_RUN_TEST_IMPL(rbt_addname) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname; + dns_name_t *name = NULL; + size_t *n; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = 1; + + dns_test_namefromstring("d.e.f.g.h.i.j.k", &fname); + name = dns_fixedname_name(&fname); + + /* Add a name that doesn't exist */ + result = dns_rbt_addname(ctx->rbt, name, n); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Now add again, should get ISC_R_EXISTS */ + n = isc_mem_get(mctx, sizeof(size_t)); + assert_non_null(n); + *n = 2; + result = dns_rbt_addname(ctx->rbt, name, n); + assert_int_equal(result, ISC_R_EXISTS); + isc_mem_put(mctx, n, sizeof(size_t)); + + test_context_teardown(ctx); +} + +/* Test deletename return values */ +ISC_RUN_TEST_IMPL(rbt_deletename) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_fixedname_t fname; + dns_name_t *name = NULL; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + /* Delete a name that doesn't exist */ + dns_test_namefromstring("z.x.y.w", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_deletename(ctx->rbt, name, false); + assert_int_equal(result, ISC_R_NOTFOUND); + + /* Now one that does */ + dns_test_namefromstring("d.e.f", &fname); + name = dns_fixedname_name(&fname); + result = dns_rbt_deletename(ctx->rbt, name, false); + assert_int_equal(result, ISC_R_NOTFOUND); + + test_context_teardown(ctx); +} + +/* Test nodechain */ +ISC_RUN_TEST_IMPL(rbt_nodechain) { + isc_result_t result; + test_context_t *ctx; + dns_fixedname_t fname, found, expect; + dns_name_t *name, *foundname, *expected; + dns_rbtnode_t *node = NULL; + dns_rbtnodechain_t chain; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + dns_rbtnodechain_init(&chain); + + dns_test_namefromstring("a", &fname); + name = dns_fixedname_name(&fname); + + result = dns_rbt_findnode(ctx->rbt, name, NULL, &node, &chain, 0, NULL, + NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + foundname = dns_fixedname_initname(&found); + + dns_test_namefromstring("a", &expect); + expected = dns_fixedname_name(&expect); + UNUSED(expected); + + result = dns_rbtnodechain_first(&chain, ctx->rbt, foundname, NULL); + assert_int_equal(result, DNS_R_NEWORIGIN); + assert_int_equal(dns_name_countlabels(foundname), 0); + + result = dns_rbtnodechain_prev(&chain, NULL, NULL); + assert_int_equal(result, ISC_R_NOMORE); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL); + assert_int_equal(result, DNS_R_NEWORIGIN); + + result = dns_rbtnodechain_next(&chain, NULL, NULL); + assert_int_equal(result, ISC_R_NOMORE); + + result = dns_rbtnodechain_last(&chain, ctx->rbt, NULL, NULL); + assert_int_equal(result, DNS_R_NEWORIGIN); + + result = dns_rbtnodechain_prev(&chain, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_rbtnodechain_invalidate(&chain); + + test_context_teardown(ctx); +} + +/* Test addname return values */ +ISC_RUN_TEST_IMPL(rbtnode_namelen) { + isc_result_t result; + test_context_t *ctx = NULL; + dns_rbtnode_t *node; + unsigned int len; + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; + + ctx = test_context_setup(); + + node = NULL; + result = insert_helper(ctx->rbt, ".", &node); + len = dns__rbtnode_namelen(node); + assert_int_equal(result, ISC_R_EXISTS); + assert_int_equal(len, 1); + node = NULL; + + result = insert_helper(ctx->rbt, "a.b.c.d.e.f.g.h.i.j.k.l.m", &node); + len = dns__rbtnode_namelen(node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(len, 27); + + node = NULL; + result = insert_helper(ctx->rbt, "isc.org", &node); + len = dns__rbtnode_namelen(node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(len, 9); + + node = NULL; + result = insert_helper(ctx->rbt, "example.com", &node); + len = dns__rbtnode_namelen(node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(len, 13); + + test_context_teardown(ctx); +} + +#if defined(DNS_BENCHMARK_TESTS) && !defined(__SANITIZE_THREAD__) + +/* + * XXXMUKS: Don't delete this code. It is useful in benchmarking the + * RBT, but we don't require it as part of the unit test runs. + */ + +static dns_fixedname_t *fnames; +static dns_name_t **names; +static int *values; + +static void * +find_thread(void *arg) { + dns_rbt_t *mytree; + isc_result_t result; + dns_rbtnode_t *node; + unsigned int j, i; + unsigned int start = 0; + + mytree = (dns_rbt_t *)arg; + while (start == 0) { + start = random() % 4000000; + } + + /* Query 32 million random names from it in each thread */ + for (j = 0; j < 8; j++) { + for (i = start; i != start - 1; i = (i + 1) % 4000000) { + node = NULL; + result = dns_rbt_findnode(mytree, names[i], NULL, &node, + NULL, DNS_RBTFIND_EMPTYDATA, + NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(node); + assert_int_equal(values[i], (intptr_t)node->data); + } + } + + return (NULL); +} + +/* Benchmark RBT implementation */ +ISC_RUN_TEST_IMPL(benchmark) { + isc_result_t result; + char namestr[sizeof("name18446744073709551616.example.org.")]; + unsigned int r; + dns_rbt_t *mytree; + dns_rbtnode_t *node; + unsigned int i; + unsigned int maxvalue = 1000000; + isc_time_t ts1, ts2; + double t; + unsigned int nthreads; + isc_thread_t threads[32]; + + srandom(time(NULL)); + + debug_mem_record = false; + + fnames = (dns_fixedname_t *)malloc(4000000 * sizeof(dns_fixedname_t)); + names = (dns_name_t **)malloc(4000000 * sizeof(dns_name_t *)); + values = (int *)malloc(4000000 * sizeof(int)); + + for (i = 0; i < 4000000; i++) { + r = ((unsigned long)random()) % maxvalue; + snprintf(namestr, sizeof(namestr), "name%u.example.org.", r); + dns_test_namefromstring(namestr, &fnames[i]); + names[i] = dns_fixedname_name(&fnames[i]); + values[i] = r; + } + + /* Create a tree. */ + mytree = NULL; + result = dns_rbt_create(mctx, NULL, NULL, &mytree); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Insert test data into the tree. */ + for (i = 0; i < maxvalue; i++) { + snprintf(namestr, sizeof(namestr), "name%u.example.org.", i); + node = NULL; + result = insert_helper(mytree, namestr, &node); + assert_int_equal(result, ISC_R_SUCCESS); + node->data = (void *)(intptr_t)i; + } + + result = isc_time_now(&ts1); + assert_int_equal(result, ISC_R_SUCCESS); + + nthreads = ISC_MIN(isc_os_ncpus(), 32); + nthreads = ISC_MAX(nthreads, 1); + for (i = 0; i < nthreads; i++) { + isc_thread_create(find_thread, mytree, &threads[i]); + } + + for (i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + result = isc_time_now(&ts2); + assert_int_equal(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("%u findnode calls, %f seconds, %f calls/second\n", + nthreads * 8 * 4000000, t / 1000000.0, + (nthreads * 8 * 4000000) / (t / 1000000.0)); + + free(values); + free(names); + free(fnames); + + dns_rbt_destroy(&mytree); +} +#endif /* defined(DNS_BENCHMARK_TESTS) && !defined(__SANITIZE_THREAD__) */ + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(rbt_create) +ISC_TEST_ENTRY(rbt_nodecount) +ISC_TEST_ENTRY(rbtnode_get_distance) +ISC_TEST_ENTRY(rbt_check_distance_random) +ISC_TEST_ENTRY(rbt_check_distance_ordered) +ISC_TEST_ENTRY(rbt_insert) +ISC_TEST_ENTRY(rbt_remove) +ISC_TEST_ENTRY(rbt_insert_and_remove) +ISC_TEST_ENTRY(rbt_findname) +ISC_TEST_ENTRY(rbt_addname) +ISC_TEST_ENTRY(rbt_deletename) +ISC_TEST_ENTRY(rbt_nodechain) +ISC_TEST_ENTRY(rbtnode_namelen) +#if defined(DNS_BENCHMARK_TESTS) && !defined(__SANITIZE_THREAD__) +ISC_TEST_ENTRY(benchmark) +#endif /* defined(DNS_BENCHMARK_TESTS) && !defined(__SANITIZE_THREAD__) */ + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rbtdb_test.c b/tests/dns/rbtdb_test.c new file mode 100644 index 0000000..59a5786 --- /dev/null +++ b/tests/dns/rbtdb_test.c @@ -0,0 +1,381 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/util.h> + +#include <dns/rbt.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> +#include <dns/rdatastruct.h> +#define KEEP_BEFORE + +/* Include the main file */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#undef CHECK +#include "rbtdb.c" +#pragma GCC diagnostic pop + +#undef CHECK +#include <tests/dns.h> + +const char *ownercase_vectors[12][2] = { + { + "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", + "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", + }, + { + "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", + "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ", + }, + { + "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ", + "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", + }, + { + "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ", + "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", + }, + { + "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVxXyYzZ", + "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvxxyyzz", + }, + { + "WwW.ExAmPlE.OrG", + "wWw.eXaMpLe.oRg", + }, + { + "_SIP.tcp.example.org", + "_sip.TCP.example.org", + }, + { + "bind-USERS.lists.example.org", + "bind-users.lists.example.org", + }, + { + "a0123456789.example.org", + "A0123456789.example.org", + }, + { + "\\000.example.org", + "\\000.example.org", + }, + { + "wWw.\\000.isc.org", + "www.\\000.isc.org", + }, + { + "\255.example.org", + "\255.example.ORG", + } +}; + +static bool +ownercase_test_one(const char *str1, const char *str2) { + isc_result_t result; + rbtdb_nodelock_t node_locks[1]; + dns_rbtdb_t rbtdb = { .node_locks = node_locks }; + dns_rbtnode_t rbtnode = { .locknum = 0 }; + rdatasetheader_t header = { 0 }; + unsigned char *raw = (unsigned char *)(&header) + sizeof(header); + dns_rdataset_t rdataset = { + .magic = DNS_RDATASET_MAGIC, + .private1 = &rbtdb, + .private2 = &rbtnode, + .private3 = raw, + .methods = &rdataset_methods, + }; + + isc_buffer_t b; + dns_fixedname_t fname1, fname2; + dns_name_t *name1, *name2; + + memset(node_locks, 0, sizeof(node_locks)); + /* Minimal initialization of the mock objects */ + NODE_INITLOCK(&rbtdb.node_locks[0].lock); + + name1 = dns_fixedname_initname(&fname1); + isc_buffer_constinit(&b, str1, strlen(str1)); + isc_buffer_add(&b, strlen(str1)); + result = dns_name_fromtext(name1, &b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + name2 = dns_fixedname_initname(&fname2); + isc_buffer_constinit(&b, str2, strlen(str2)); + isc_buffer_add(&b, strlen(str2)); + result = dns_name_fromtext(name2, &b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Store the case from name1 */ + dns_rdataset_setownercase(&rdataset, name1); + + assert_true(CASESET(&header)); + + /* Retrieve the case to name2 */ + dns_rdataset_getownercase(&rdataset, name2); + + NODE_DESTROYLOCK(&rbtdb.node_locks[0].lock); + + return (dns_name_caseequal(name1, name2)); +} + +ISC_RUN_TEST_IMPL(ownercase) { + UNUSED(state); + + for (size_t n = 0; n < ARRAY_SIZE(ownercase_vectors); n++) { + assert_true(ownercase_test_one(ownercase_vectors[n][0], + ownercase_vectors[n][1])); + } + + assert_false(ownercase_test_one("W.example.org", "\\000.example.org")); + + /* Ö and ö in ISO Latin 1 */ + assert_false(ownercase_test_one("\\216", "\\246")); +} + +ISC_RUN_TEST_IMPL(setownercase) { + isc_result_t result; + rbtdb_nodelock_t node_locks[1]; + dns_rbtdb_t rbtdb = { .node_locks = node_locks }; + dns_rbtnode_t rbtnode = { .locknum = 0 }; + rdatasetheader_t header = { 0 }; + unsigned char *raw = (unsigned char *)(&header) + sizeof(header); + dns_rdataset_t rdataset = { + .magic = DNS_RDATASET_MAGIC, + .private1 = &rbtdb, + .private2 = &rbtnode, + .private3 = raw, + .methods = &rdataset_methods, + }; + const char *str1 = + "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; + + isc_buffer_t b; + dns_fixedname_t fname1, fname2; + dns_name_t *name1, *name2; + + UNUSED(state); + + /* Minimal initialization of the mock objects */ + memset(node_locks, 0, sizeof(node_locks)); + NODE_INITLOCK(&rbtdb.node_locks[0].lock); + + name1 = dns_fixedname_initname(&fname1); + isc_buffer_constinit(&b, str1, strlen(str1)); + isc_buffer_add(&b, strlen(str1)); + result = dns_name_fromtext(name1, &b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + name2 = dns_fixedname_initname(&fname2); + isc_buffer_constinit(&b, str1, strlen(str1)); + isc_buffer_add(&b, strlen(str1)); + result = dns_name_fromtext(name2, &b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(CASESET(&header)); + + /* Retrieve the case to name2 */ + dns_rdataset_getownercase(&rdataset, name2); + + NODE_DESTROYLOCK(&rbtdb.node_locks[0].lock); + + assert_true(dns_name_caseequal(name1, name2)); +} + +/* + * No operation water() callback. We need it to cause overmem condition, but + * nothing has to be done in the callback. + */ +static void +overmempurge_water(void *arg, int mark) { + UNUSED(arg); + UNUSED(mark); +} + +/* + * Add to a cache DB 'db' an rdataset of type 'rtype' at a name + * <idx>.example.com. The rdataset would contain one data, and rdata_len is + * its length. 'rtype' is supposed to be some private type whose data can be + * arbitrary (and it doesn't matter in this test). + */ +static void +overmempurge_addrdataset(dns_db_t *db, isc_stdtime_t now, int idx, + dns_rdatatype_t rtype, size_t rdata_len, + bool longname) { + isc_result_t result; + dns_rdata_t rdata; + dns_dbnode_t *node = NULL; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + dns_fixedname_t fname; + dns_name_t *name; + char namebuf[DNS_NAME_FORMATSIZE]; + unsigned char rdatabuf[65535] = { 0 }; /* large enough for any valid + RDATA */ + + REQUIRE(rdata_len <= sizeof(rdatabuf)); + + if (longname) { + /* + * Build a longest possible name (in wire format) that would + * result in a new rbt node with the long name data. + */ + snprintf(namebuf, sizeof(namebuf), + "%010d.%010dabcdef%010dabcdef%010dabcdef%010dabcde." + "%010dabcdef%010dabcdef%010dabcdef%010dabcde." + "%010dabcdef%010dabcdef%010dabcdef%010dabcde." + "%010dabcdef%010dabcdef%010dabcdef01.", + idx, idx, idx, idx, idx, idx, idx, idx, idx, idx, idx, + idx, idx, idx, idx, idx); + } else { + snprintf(namebuf, sizeof(namebuf), "%d.example.com.", idx); + } + dns_test_namefromstring(namebuf, &fname); + name = dns_fixedname_name(&fname); + + result = dns_db_findnode(db, name, true, &node); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(node); + + dns_rdata_init(&rdata); + rdata.length = rdata_len; + rdata.data = rdatabuf; + rdata.rdclass = dns_rdataclass_in; + rdata.type = rtype; + + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = dns_rdataclass_in; + rdatalist.type = rtype; + rdatalist.ttl = 3600; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + dns_rdataset_init(&rdataset); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + + result = dns_db_addrdataset(db, node, NULL, now, &rdataset, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_db_detachnode(db, &node); +} + +ISC_RUN_TEST_IMPL(overmempurge_bigrdata) { + size_t maxcache = 2097152U; /* 2MB - same as DNS_CACHE_MINSIZE */ + size_t hiwater = maxcache - (maxcache >> 3); /* borrowed from cache.c */ + size_t lowater = maxcache - (maxcache >> 2); /* ditto */ + isc_result_t result; + dns_db_t *db = NULL; + isc_mem_t *mctx2 = NULL; + isc_stdtime_t now; + size_t i; + + isc_stdtime_get(&now); + isc_mem_create(&mctx2); + + result = dns_db_create(mctx2, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_mem_setwater(mctx2, overmempurge_water, NULL, hiwater, lowater); + + /* + * Add cache entries with minimum size of data until 'overmem' + * condition is triggered. + * This should eventually happen, but we also limit the number of + * iteration to avoid an infinite loop in case something gets wrong. + */ + for (i = 0; !isc_mem_isovermem(mctx2) && i < (maxcache / 10); i++) { + overmempurge_addrdataset(db, now, i, 50053, 0, false); + } + assert_true(isc_mem_isovermem(mctx2)); + + /* + * Then try to add the same number of entries, each has very large data. + * 'overmem purge' should keep the total cache size from not exceeding + * the 'hiwater' mark too much. So we should be able to assume the + * cache size doesn't reach the "max". + */ + while (i-- > 0) { + overmempurge_addrdataset(db, now, i, 50054, 65535, false); + assert_true(isc_mem_inuse(mctx2) < maxcache); + } + + dns_db_detach(&db); + isc_mem_destroy(&mctx2); +} + +ISC_RUN_TEST_IMPL(overmempurge_longname) { + size_t maxcache = 2097152U; /* 2MB - same as DNS_CACHE_MINSIZE */ + size_t hiwater = maxcache - (maxcache >> 3); /* borrowed from cache.c */ + size_t lowater = maxcache - (maxcache >> 2); /* ditto */ + isc_result_t result; + dns_db_t *db = NULL; + isc_mem_t *mctx2 = NULL; + isc_stdtime_t now; + size_t i; + + isc_stdtime_get(&now); + isc_mem_create(&mctx2); + + result = dns_db_create(mctx2, "rbt", dns_rootname, dns_dbtype_cache, + dns_rdataclass_in, 0, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_mem_setwater(mctx2, overmempurge_water, NULL, hiwater, lowater); + + /* + * Add cache entries with minimum size of data until 'overmem' + * condition is triggered. + * This should eventually happen, but we also limit the number of + * iteration to avoid an infinite loop in case something gets wrong. + */ + for (i = 0; !isc_mem_isovermem(mctx2) && i < (maxcache / 10); i++) { + overmempurge_addrdataset(db, now, i, 50053, 0, false); + } + assert_true(isc_mem_isovermem(mctx2)); + + /* + * Then try to add the same number of entries, each has very large data. + * 'overmem purge' should keep the total cache size from not exceeding + * the 'hiwater' mark too much. So we should be able to assume the + * cache size doesn't reach the "max". + */ + while (i-- > 0) { + overmempurge_addrdataset(db, now, i, 50054, 0, true); + assert_true(isc_mem_inuse(mctx2) < maxcache); + } + + dns_db_detach(&db); + isc_mem_destroy(&mctx2); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(ownercase) +ISC_TEST_ENTRY(setownercase) +ISC_TEST_ENTRY(overmempurge_bigrdata) +ISC_TEST_ENTRY(overmempurge_longname) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rdata_test.c b/tests/dns/rdata_test.c new file mode 100644 index 0000000..73e4526 --- /dev/null +++ b/tests/dns/rdata_test.c @@ -0,0 +1,3121 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING + +#include <openssl_shim.h> + +#include <openssl/err.h> + +#include <isc/cmocka.h> +#include <isc/commandline.h> +#include <isc/hex.h> +#include <isc/lex.h> +#include <isc/print.h> +#include <isc/stdio.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <dns/rdata.h> + +#include <tests/dns.h> + +static bool debug = false; + +/* + * An array of these structures is passed to compare_ok(). + */ +struct compare_ok { + const char *text1; /* text passed to fromtext_*() */ + const char *text2; /* text passed to fromtext_*() */ + int answer; /* -1, 0, 1 */ + int lineno; /* source line defining this RDATA */ +}; +typedef struct compare_ok compare_ok_t; + +struct textvsunknown { + const char *text1; + const char *text2; +}; +typedef struct textvsunknown textvsunknown_t; + +/* + * An array of these structures is passed to check_text_ok(). + */ +typedef struct text_ok { + const char *text_in; /* text passed to fromtext_*() */ + const char *text_out; /* text expected from totext_*(); + * NULL indicates text_in is invalid */ + unsigned int loop; +} text_ok_t; + +/* + * An array of these structures is passed to check_wire_ok(). + */ +typedef struct wire_ok { + unsigned char data[512]; /* RDATA in wire format */ + size_t len; /* octets of data to parse */ + bool ok; /* is this RDATA valid? */ + unsigned int loop; +} wire_ok_t; + +#define COMPARE(r1, r2, answer) \ + { \ + r1, r2, answer, __LINE__ \ + } +#define COMPARE_SENTINEL() \ + { \ + NULL, NULL, 0, __LINE__ \ + } + +#define TEXT_VALID_CHANGED(data_in, data_out) \ + { \ + data_in, data_out, 0 \ + } +#define TEXT_VALID(data) \ + { \ + data, data, 0 \ + } +#define TEXT_VALID_LOOP(loop, data) \ + { \ + data, data, loop \ + } +#define TEXT_VALID_LOOPCHG(loop, data_in, data_out) \ + { \ + data_in, data_out, loop \ + } +#define TEXT_INVALID(data) \ + { \ + data, NULL, 0 \ + } +#define TEXT_SENTINEL() TEXT_INVALID(NULL) + +#define VARGC(...) (sizeof((unsigned char[]){ __VA_ARGS__ })) +#define WIRE_TEST(ok, loop, ...) \ + { \ + { __VA_ARGS__ }, VARGC(__VA_ARGS__), ok, loop \ + } +#define WIRE_VALID(...) WIRE_TEST(true, 0, __VA_ARGS__) +#define WIRE_VALID_LOOP(loop, ...) WIRE_TEST(true, loop, __VA_ARGS__) +/* + * WIRE_INVALID() test cases must always have at least one octet specified to + * distinguish them from WIRE_SENTINEL(). Use the 'empty_ok' parameter passed + * to check_wire_ok() for indicating whether empty RDATA is allowed for a given + * RR type or not. + */ +#define WIRE_INVALID(FIRST, ...) WIRE_TEST(false, 0, FIRST, __VA_ARGS__) +#define WIRE_SENTINEL() WIRE_TEST(false, 0) + +static void +detect_uncleared_libcrypto_error(void) { + const char *file, *func, *data; + int line, flags; + long err; + bool leak = false; + while ((err = ERR_get_error_all(&file, &line, &func, &data, &flags)) != + 0L) + { + fprintf(stderr, + "# Uncleared libcrypto error: %s:%d %s %s %ld %x\n", + file, line, func, data, err, flags); + leak = true; + } + assert_false(leak); +} + +/* + * Call dns_rdata_fromwire() for data in 'src', which is 'srclen' octets in + * size and represents RDATA of given 'type' and 'class'. Store the resulting + * uncompressed wire form in 'dst', which is 'dstlen' octets in size, and make + * 'rdata' refer to that uncompressed wire form. + */ +static isc_result_t +wire_to_rdata(const unsigned char *src, size_t srclen, dns_rdataclass_t rdclass, + dns_rdatatype_t type, unsigned char *dst, size_t dstlen, + dns_rdata_t *rdata) { + isc_buffer_t source, target; + dns_decompress_t dctx; + isc_result_t result; + + /* + * Set up len-octet buffer pointing at data. + */ + isc_buffer_constinit(&source, src, srclen); + isc_buffer_add(&source, srclen); + isc_buffer_setactive(&source, srclen); + + /* + * Initialize target buffer. + */ + isc_buffer_init(&target, dst, dstlen); + + /* + * Try converting input 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); + detect_uncleared_libcrypto_error(); + + return (result); +} + +/* + * Call dns_rdata_towire() for rdata and write to result to dst. + */ +static isc_result_t +rdata_towire(dns_rdata_t *rdata, unsigned char *dst, size_t dstlen, + size_t *length) { + isc_buffer_t target; + dns_compress_t cctx; + isc_result_t result; + + /* + * Initialize target buffer. + */ + isc_buffer_init(&target, dst, dstlen); + + /* + * Try converting input data into uncompressed wire form. + */ + dns_compress_init(&cctx, -1, mctx); + result = dns_rdata_towire(rdata, &cctx, &target); + detect_uncleared_libcrypto_error(); + dns_compress_invalidate(&cctx); + + *length = isc_buffer_usedlength(&target); + + return (result); +} + +static isc_result_t +additionaldata_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype, + dns_rdataset_t *found) { + UNUSED(arg); + UNUSED(name); + UNUSED(qtype); + UNUSED(found); + return (ISC_R_SUCCESS); +} + +/* + * call dns_rdata_additionaldata() for rdata. + */ +static isc_result_t +rdata_additionadata(dns_rdata_t *rdata) { + return (dns_rdata_additionaldata(rdata, dns_rootname, additionaldata_cb, + NULL)); +} + +/* + * Call dns_rdata_checknames() with various owner names chosen to + * match well known forms. + * + * We are currently only checking that the calls do not trigger + * assertion failures. + * + * XXXMPA A future extension could be to record the expected + * result and the expected value of 'bad'. + */ +static void +rdata_checknames(dns_rdata_t *rdata) { + dns_fixedname_t fixed, bfixed; + dns_name_t *name, *bad; + isc_result_t result; + + name = dns_fixedname_initname(&fixed); + bad = dns_fixedname_initname(&bfixed); + + (void)dns_rdata_checknames(rdata, dns_rootname, NULL); + (void)dns_rdata_checknames(rdata, dns_rootname, bad); + + result = dns_name_fromstring(name, "example.net", 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + (void)dns_rdata_checknames(rdata, name, NULL); + (void)dns_rdata_checknames(rdata, name, bad); + + result = dns_name_fromstring(name, "in-addr.arpa", 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + (void)dns_rdata_checknames(rdata, name, NULL); + (void)dns_rdata_checknames(rdata, name, bad); + + result = dns_name_fromstring(name, "ip6.arpa", 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + (void)dns_rdata_checknames(rdata, name, NULL); + (void)dns_rdata_checknames(rdata, name, bad); +} + +/* + * 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, + unsigned int loop) { + 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]; + unsigned int count = 0; + + rdata_struct = isc_mem_allocate(mctx, structsize); + assert_non_null(rdata_struct); + + /* + * Convert from uncompressed wire form into type-specific struct. + */ + result = dns_rdata_tostruct(rdata, rdata_struct, NULL); + detect_uncleared_libcrypto_error(); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * 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); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Ensure results are consistent. + */ + assert_int_equal(isc_buffer_usedlength(&target), rdata->length); + + assert_memory_equal(buf, rdata->data, rdata->length); + + /* + * Check that one can walk hip rendezvous servers and + * https/svcb parameters. + */ + switch (type) { + case dns_rdatatype_hip: { + dns_rdata_hip_t *hip = rdata_struct; + + for (result = dns_rdata_hip_first(hip); result == ISC_R_SUCCESS; + result = dns_rdata_hip_next(hip)) + { + dns_name_t name; + dns_name_init(&name, NULL); + dns_rdata_hip_current(hip, &name); + assert_int_not_equal(dns_name_countlabels(&name), 0); + assert_true(dns_name_isabsolute(&name)); + count++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(count, loop); + break; + } + case dns_rdatatype_https: { + dns_rdata_in_https_t *https = rdata_struct; + + for (result = dns_rdata_in_https_first(https); + result == ISC_R_SUCCESS; + result = dns_rdata_in_https_next(https)) + { + isc_region_t region; + dns_rdata_in_https_current(https, ®ion); + assert_true(region.length >= 4); + count++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(count, loop); + break; + } + case dns_rdatatype_svcb: { + dns_rdata_in_svcb_t *svcb = rdata_struct; + + for (result = dns_rdata_in_svcb_first(svcb); + result == ISC_R_SUCCESS; + result = dns_rdata_in_svcb_next(svcb)) + { + isc_region_t region; + dns_rdata_in_svcb_current(svcb, ®ion); + assert_true(region.length >= 4); + count++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(count, loop); + break; + } + } + + isc_mem_free(mctx, rdata_struct); +} + +/* + * Check whether converting supplied text form RDATA into uncompressed wire + * form succeeds (tests fromtext_*()). If so, try converting it back into text + * form and see if it results in the original text (tests totext_*()). + */ +static void +check_text_ok_single(const text_ok_t *text_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + unsigned char buf_fromtext[1024], buf_fromwire[1024], buf_towire[1024]; + dns_rdata_t rdata = DNS_RDATA_INIT, rdata2 = DNS_RDATA_INIT; + char buf_totext[1024] = { 0 }; + isc_buffer_t target; + isc_result_t result; + size_t length = 0; + + if (debug) { + fprintf(stdout, "#check_text_ok_single(%s)\n", + text_ok->text_in); + } + /* + * Try converting text form RDATA into uncompressed wire form. + */ + result = dns_test_rdatafromstring(&rdata, rdclass, type, buf_fromtext, + sizeof(buf_fromtext), + text_ok->text_in, false); + /* + * Check whether result is as expected. + */ + if (text_ok->text_out != NULL) { + if (debug && result != ISC_R_SUCCESS) { + fprintf(stdout, "# '%s'\n", text_ok->text_in); + fprintf(stdout, "# result=%s\n", + isc_result_totext(result)); + } + assert_int_equal(result, ISC_R_SUCCESS); + } else { + if (debug && result == ISC_R_SUCCESS) { + fprintf(stdout, "#'%s'\n", text_ok->text_in); + } + assert_int_not_equal(result, ISC_R_SUCCESS); + } + + /* + * If text form RDATA was not parsed correctly, performing any + * additional checks is pointless. + */ + if (result != ISC_R_SUCCESS) { + return; + } + + /* + * Try converting uncompressed wire form RDATA back into text form and + * check whether the resulting text is the same as the original one. + */ + isc_buffer_init(&target, buf_totext, sizeof(buf_totext)); + result = dns_rdata_totext(&rdata, NULL, &target); + detect_uncleared_libcrypto_error(); + if (result != ISC_R_SUCCESS && debug) { + size_t i; + fprintf(stdout, "# dns_rdata_totext -> %s", + isc_result_totext(result)); + for (i = 0; i < rdata.length; i++) { + if ((i % 16) == 0) { + fprintf(stdout, "\n#"); + } + fprintf(stdout, " %02x", rdata.data[i]); + } + fprintf(stdout, "\n"); + } + assert_int_equal(result, ISC_R_SUCCESS); + /* + * Ensure buf_totext is properly NUL terminated as dns_rdata_totext() + * may attempt different output formats writing into the apparently + * unused part of the buffer. + */ + isc_buffer_putuint8(&target, 0); + if (debug && strcmp(buf_totext, text_ok->text_out) != 0) { + fprintf(stdout, "# '%s' != '%s'\n", buf_totext, + text_ok->text_out); + } + assert_string_equal(buf_totext, text_ok->text_out); + + if (debug) { + fprintf(stdout, "#dns_rdata_totext -> '%s'\n", buf_totext); + } + + /* + * Ensure that fromtext_*() output is valid input for fromwire_*(). + */ + result = wire_to_rdata(rdata.data, rdata.length, rdclass, type, + buf_fromwire, sizeof(buf_fromwire), &rdata2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdata.length, rdata2.length); + assert_memory_equal(rdata.data, buf_fromwire, rdata.length); + + /* + * Ensure that fromtext_*() output is valid input for towire_*(). + */ + result = rdata_towire(&rdata, buf_towire, sizeof(buf_towire), &length); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdata.length, length); + assert_memory_equal(rdata.data, buf_towire, length); + + /* + * Test that additionaldata_*() succeeded. + */ + result = rdata_additionadata(&rdata); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Exercise checknames_*(). + */ + rdata_checknames(&rdata); + + /* + * Perform two-way conversion checks between uncompressed wire form and + * type-specific struct. + */ + check_struct_conversions(&rdata, structsize, text_ok->loop); +} + +/* + * Test whether converting rdata to text form and then parsing the result of + * that conversion again results in the same uncompressed wire form. This + * checks whether totext_*() output is parsable by fromtext_*() for given RR + * class and type. + * + * This function is called for every input RDATA which is successfully parsed + * by check_wire_ok_single() and whose type is not a meta-type. + */ +static void +check_text_conversions(dns_rdata_t *rdata) { + char buf_totext[1024] = { 0 }; + unsigned char buf_fromtext[1024]; + isc_result_t result; + isc_buffer_t target; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + + /* + * Convert uncompressed wire form RDATA into text form. This + * conversion must succeed since input RDATA was successfully + * parsed by check_wire_ok_single(). + */ + isc_buffer_init(&target, buf_totext, sizeof(buf_totext)); + result = dns_rdata_totext(rdata, NULL, &target); + detect_uncleared_libcrypto_error(); + assert_int_equal(result, ISC_R_SUCCESS); + /* + * Ensure buf_totext is properly NUL terminated as dns_rdata_totext() + * may attempt different output formats writing into the apparently + * unused part of the buffer. + */ + isc_buffer_putuint8(&target, 0); + if (debug) { + fprintf(stdout, "#'%s'\n", buf_totext); + } + + /* + * Try parsing text form RDATA output by dns_rdata_totext() again. + */ + result = dns_test_rdatafromstring(&rdata2, rdata->rdclass, rdata->type, + buf_fromtext, sizeof(buf_fromtext), + buf_totext, false); + if (debug && result != ISC_R_SUCCESS) { + fprintf(stdout, "# result = %s\n", isc_result_totext(result)); + fprintf(stdout, "# '%s'\n", buf_fromtext); + } + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdata2.length, rdata->length); + assert_memory_equal(buf_fromtext, rdata->data, rdata->length); +} + +/* + * Test whether converting rdata to multi-line text form and then parsing the + * result of that conversion again results in the same uncompressed wire form. + * This checks whether multi-line totext_*() output is parsable by fromtext_*() + * for given RR class and type. + * + * This function is called for every input RDATA which is successfully parsed + * by check_wire_ok_single() and whose type is not a meta-type. + */ +static void +check_multiline_text_conversions(dns_rdata_t *rdata) { + char buf_totext[1024] = { 0 }; + unsigned char buf_fromtext[1024]; + isc_result_t result; + isc_buffer_t target; + dns_rdata_t rdata2 = DNS_RDATA_INIT; + unsigned int flags; + + /* + * Convert uncompressed wire form RDATA into multi-line text form. + * This conversion must succeed since input RDATA was successfully + * parsed by check_wire_ok_single(). + */ + isc_buffer_init(&target, buf_totext, sizeof(buf_totext)); + flags = dns_master_styleflags(&dns_master_style_default); + result = dns_rdata_tofmttext(rdata, dns_rootname, flags, 80 - 32, 4, + "\n", &target); + detect_uncleared_libcrypto_error(); + assert_int_equal(result, ISC_R_SUCCESS); + /* + * Ensure buf_totext is properly NUL terminated as + * dns_rdata_tofmttext() may attempt different output formats + * writing into the apparently unused part of the buffer. + */ + isc_buffer_putuint8(&target, 0); + if (debug) { + fprintf(stdout, "#'%s'\n", buf_totext); + } + + /* + * Try parsing multi-line text form RDATA output by + * dns_rdata_tofmttext() again. + */ + result = dns_test_rdatafromstring(&rdata2, rdata->rdclass, rdata->type, + buf_fromtext, sizeof(buf_fromtext), + buf_totext, false); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdata2.length, rdata->length); + assert_memory_equal(buf_fromtext, rdata->data, rdata->length); +} + +/* + * Test whether supplied wire form RDATA is properly handled as being either + * valid or invalid for an RR of given rdclass and type. + */ +static void +check_wire_ok_single(const wire_ok_t *wire_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + unsigned char buf[1024], buf_towire[1024]; + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + size_t length = 0; + + /* + * Try converting wire data into uncompressed wire form. + */ + result = wire_to_rdata(wire_ok->data, wire_ok->len, rdclass, type, buf, + sizeof(buf), &rdata); + /* + * Check whether result is as expected. + */ + if (wire_ok->ok) { + assert_int_equal(result, ISC_R_SUCCESS); + } else { + assert_int_not_equal(result, ISC_R_SUCCESS); + } + + if (result != ISC_R_SUCCESS) { + return; + } + + /* + * If data was parsed correctly, perform two-way conversion checks + * between uncompressed wire form and type-specific struct. + * + * If the RR type is not a meta-type, additionally perform two-way + * conversion checks between: + * + * - uncompressed wire form and text form, + * - uncompressed wire form and multi-line text form. + */ + check_struct_conversions(&rdata, structsize, wire_ok->loop); + if (!dns_rdatatype_ismeta(rdata.type)) { + check_text_conversions(&rdata); + check_multiline_text_conversions(&rdata); + } + + /* + * Ensure that fromwire_*() output is valid input for towire_*(). + */ + result = rdata_towire(&rdata, buf_towire, sizeof(buf_towire), &length); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(rdata.length, length); + assert_memory_equal(rdata.data, buf_towire, length); + + /* + * Test that additionaldata_*() succeeded. + */ + result = rdata_additionadata(&rdata); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Exercise checknames_*(). + */ + rdata_checknames(&rdata); +} + +/* + * Test fromtext_*() and totext_*() routines for given RR class and type for + * each text form RDATA in the supplied array. See the comment for + * check_text_ok_single() for an explanation of how exactly these routines are + * tested. + */ +static void +check_text_ok(const text_ok_t *text_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + size_t i; + + /* + * Check all entries in the supplied array. + */ + for (i = 0; text_ok[i].text_in != NULL; i++) { + check_text_ok_single(&text_ok[i], rdclass, type, structsize); + } +} + +/* + * For each wire form RDATA in the supplied array, check whether it is properly + * handled as being either valid or invalid for an RR of given rdclass and + * type, then check whether trying to process a zero-length wire data buffer + * yields the expected result. This checks whether the fromwire_*() routine + * for given RR class and type behaves as expected. + */ +static void +check_wire_ok(const wire_ok_t *wire_ok, bool empty_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type, size_t structsize) { + wire_ok_t empty_wire = WIRE_TEST(empty_ok, 0); + size_t i; + + /* + * Check all entries in the supplied array. + */ + for (i = 0; wire_ok[i].len != 0; i++) { + if (debug) { + fprintf(stderr, "calling check_wire_ok_single on %zu\n", + i); + } + check_wire_ok_single(&wire_ok[i], rdclass, type, structsize); + } + + /* + * Check empty wire data. + */ + check_wire_ok_single(&empty_wire, rdclass, type, structsize); +} + +/* + * Check that two records compare as expected with dns_rdata_compare(). + */ +static void +check_compare_ok_single(const compare_ok_t *compare_ok, + dns_rdataclass_t rdclass, dns_rdatatype_t type) { + dns_rdata_t rdata1 = DNS_RDATA_INIT, rdata2 = DNS_RDATA_INIT; + unsigned char buf1[1024], buf2[1024]; + isc_result_t result; + int answer; + + result = dns_test_rdatafromstring(&rdata1, rdclass, type, buf1, + sizeof(buf1), compare_ok->text1, + false); + if (result != ISC_R_SUCCESS) { + fail_msg("# line %d: '%s': expected success, got failure", + compare_ok->lineno, compare_ok->text1); + } + + result = dns_test_rdatafromstring(&rdata2, rdclass, type, buf2, + sizeof(buf2), compare_ok->text2, + false); + + if (result != ISC_R_SUCCESS) { + fail_msg("# line %d: '%s': expected success, got failure", + compare_ok->lineno, compare_ok->text2); + } + + answer = dns_rdata_compare(&rdata1, &rdata2); + detect_uncleared_libcrypto_error(); + if (compare_ok->answer == 0 && answer != 0) { + fail_msg("# line %d: dns_rdata_compare('%s', '%s'): " + "expected equal, got %s", + compare_ok->lineno, compare_ok->text1, + compare_ok->text2, + (answer > 0) ? "greater than" : "less than"); + } + if (compare_ok->answer < 0 && answer >= 0) { + fail_msg("# line %d: dns_rdata_compare('%s', '%s'): " + "expected less than, got %s", + compare_ok->lineno, compare_ok->text1, + compare_ok->text2, + (answer == 0) ? "equal" : "greater than"); + } + if (compare_ok->answer > 0 && answer <= 0) { + fail_msg("line %d: dns_rdata_compare('%s', '%s'): " + "expected greater than, got %s", + compare_ok->lineno, compare_ok->text1, + compare_ok->text2, + (answer == 0) ? "equal" : "less than"); + } +} + +/* + * Check that all the records sets in compare_ok compare as expected + * with dns_rdata_compare(). + */ +static void +check_compare_ok(const compare_ok_t *compare_ok, dns_rdataclass_t rdclass, + dns_rdatatype_t type) { + size_t i; + /* + * Check all entries in the supplied array. + */ + for (i = 0; compare_ok[i].text1 != NULL; i++) { + check_compare_ok_single(&compare_ok[i], rdclass, type); + } +} + +/* + * Test whether supplied sets of text form and/or wire form RDATA are handled + * as expected. + * + * The empty_ok argument denotes whether an attempt to parse a zero-length wire + * data buffer should succeed or not (it is valid for some RR types). There is + * no point in performing a similar check for empty text form RDATA, because + * dns_rdata_fromtext() returns ISC_R_UNEXPECTEDEND before calling fromtext_*() + * for the given RR class and type. + */ +static void +check_rdata(const text_ok_t *text_ok, const wire_ok_t *wire_ok, + const compare_ok_t *compare_ok, bool empty_ok, + dns_rdataclass_t rdclass, dns_rdatatype_t type, size_t structsize) { + 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); + } + if (compare_ok != NULL) { + check_compare_ok(compare_ok, rdclass, type); + } +} + +/* + * Check presentation vs unknown format of the record. + */ +static void +check_textvsunknown_single(const textvsunknown_t *textvsunknown, + dns_rdataclass_t rdclass, dns_rdatatype_t type) { + dns_rdata_t rdata1 = DNS_RDATA_INIT, rdata2 = DNS_RDATA_INIT; + unsigned char buf1[1024], buf2[1024]; + isc_result_t result; + + result = dns_test_rdatafromstring(&rdata1, rdclass, type, buf1, + sizeof(buf1), textvsunknown->text1, + false); + if (debug && result != ISC_R_SUCCESS) { + fprintf(stdout, "# '%s'\n", textvsunknown->text1); + fprintf(stdout, "# result=%s\n", isc_result_totext(result)); + } + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_rdatafromstring(&rdata2, rdclass, type, buf2, + sizeof(buf2), textvsunknown->text2, + false); + if (debug && result != ISC_R_SUCCESS) { + fprintf(stdout, "# '%s'\n", textvsunknown->text2); + fprintf(stdout, "# result=%s\n", isc_result_totext(result)); + } + assert_int_equal(result, ISC_R_SUCCESS); + if (debug && rdata1.length != rdata2.length) { + fprintf(stdout, "# '%s'\n", textvsunknown->text1); + fprintf(stdout, "# rdata1.length (%u) != rdata2.length (%u)\n", + rdata1.length, rdata2.length); + } + assert_int_equal(rdata1.length, rdata2.length); + if (debug && memcmp(rdata1.data, rdata2.data, rdata1.length) != 0) { + unsigned int i; + fprintf(stdout, "# '%s'\n", textvsunknown->text1); + for (i = 0; i < rdata1.length; i++) { + if (rdata1.data[i] != rdata2.data[i]) { + fprintf(stderr, "# %u: %02x != %02x\n", i, + rdata1.data[i], rdata2.data[i]); + } + } + } + assert_memory_equal(rdata1.data, rdata2.data, rdata1.length); +} + +static void +check_textvsunknown(const textvsunknown_t *textvsunknown, + dns_rdataclass_t rdclass, dns_rdatatype_t type) { + size_t i; + + /* + * Check all entries in the supplied array. + */ + for (i = 0; textvsunknown[i].text1 != NULL; i++) { + check_textvsunknown_single(&textvsunknown[i], rdclass, type); + } +} + +/* + * Common tests for RR types based on KEY that require key data: + * + * - CDNSKEY (RFC 7344) + * - DNSKEY (RFC 4034) + * - RKEY (draft-reid-dnsext-rkey-00) + */ +static void +key_required(void **state, dns_rdatatype_t type, size_t size) { + wire_ok_t wire_ok[] = { /* + * RDATA must be at least 5 octets in size: + * + * - 2 octets for Flags, + * - 1 octet for Protocol, + * - 1 octet for Algorithm, + * - Public Key must not be empty. + * + * RFC 2535 section 3.1.2 allows the Public Key + * to be empty if bits 0-1 of Flags are both + * set, but that only applies to KEY records: + * for the RR types tested here, the Public Key + * must not be empty. + */ + WIRE_INVALID(0x00), + WIRE_INVALID(0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00), + WIRE_INVALID(0xc0, 0x00, 0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00, 0x00), + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00), + WIRE_SENTINEL() + }; + + UNUSED(state); + + check_rdata(NULL, wire_ok, NULL, false, dns_rdataclass_in, type, size); +} + +/* APL RDATA manipulations */ +ISC_RUN_TEST_IMPL(apl) { + text_ok_t text_ok[] = { + /* empty list */ + TEXT_VALID(""), + /* min,max prefix IPv4 */ + TEXT_VALID("1:0.0.0.0/0"), TEXT_VALID("1:127.0.0.1/32"), + /* min,max prefix IPv6 */ + TEXT_VALID("2:::/0"), TEXT_VALID("2:::1/128"), + /* negated */ + TEXT_VALID("!1:0.0.0.0/0"), TEXT_VALID("!1:127.0.0.1/32"), + TEXT_VALID("!2:::/0"), TEXT_VALID("!2:::1/128"), + /* bits set after prefix length - not disallowed */ + TEXT_VALID("1:127.0.0.0/0"), TEXT_VALID("2:8000::/0"), + /* multiple */ + TEXT_VALID("1:0.0.0.0/0 1:127.0.0.1/32"), + TEXT_VALID("1:0.0.0.0/0 !1:127.0.0.1/32"), + /* family 0, prefix 0, positive */ + TEXT_VALID("\\# 4 00000000"), + /* family 0, prefix 0, negative */ + TEXT_VALID("\\# 4 00000080"), + /* prefix too long */ + TEXT_INVALID("1:0.0.0.0/33"), TEXT_INVALID("2:::/129"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { /* zero length */ + WIRE_VALID(), + /* prefix too big IPv4 */ + WIRE_INVALID(0x00, 0x01, 33U, 0x00), + /* prefix too big IPv6 */ + WIRE_INVALID(0x00, 0x02, 129U, 0x00), + /* trailing zero octet in afdpart */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x01, 0x00), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, true, dns_rdataclass_in, + dns_rdatatype_apl, sizeof(dns_rdata_in_apl_t)); +} + +/* + * http://broadband-forum.org/ftp/pub/approved-specs/af-saa-0069.000.pdf + * + * ATMA RR’s have the following RDATA format: + * + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | FORMAT | | + * +--+--+--+--+--+--+--+--+ | + * / ADDRESS / + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * The fields have the following meaning: + * + * * FORMAT: One octet that indicates the format of ADDRESS. The two + * possible values for FORMAT are value 0 indicating ATM End System Address + * (AESA) format and value 1 indicating E.164 format. + * + * * ADDRESS: Variable length string of octets containing the ATM address of + * the node to which this RR pertains. + * + * When the format value is 0, indicating that the address is in AESA format, + * the address is coded as described in ISO 8348/AD 2 using the preferred + * binary encoding of the ISO NSAP format. When the format value is 1, + * indicating that the address is in E.164 format, the Address/Number Digits + * appear in the order in which they would be entered on a numeric keypad. + * Digits are coded in IA5 characters with the leftmost bit of each digit set + * to 0. This ATM address appears in ATM End System Address Octets field (AESA + * format) or the Address/Number Digits field (E.164 format) of the Called + * party number information element [ATMUNI3.1]. Subaddress information is + * intentionally not included because E.164 subaddress information is used for + * routing. + * + * ATMA RRs cause no additional section processing. + */ +ISC_RUN_TEST_IMPL(atma) { + text_ok_t text_ok[] = { TEXT_VALID("00"), + TEXT_VALID_CHANGED("0.0", "00"), + /* + * multiple consecutive periods + */ + TEXT_INVALID("0..0"), + /* + * trailing period + */ + TEXT_INVALID("00."), + /* + * leading period + */ + TEXT_INVALID(".00"), + /* + * Not full octets. + */ + TEXT_INVALID("000"), + /* + * E.164 + */ + TEXT_VALID("+61200000000"), + /* + * E.164 with periods + */ + TEXT_VALID_CHANGED("+61.2.0000.0000", "+6120000" + "0000"), + /* + * E.164 with period at end + */ + TEXT_INVALID("+61200000000."), + /* + * E.164 with multiple consecutive periods + */ + TEXT_INVALID("+612..00000000"), + /* + * E.164 with period before the leading digit. + */ + TEXT_INVALID("+.61200000000"), + /* + * Sentinel. + */ + TEXT_SENTINEL() }; + wire_ok_t wire_ok[] = { + /* + * Too short. + */ + WIRE_INVALID(0x00), WIRE_INVALID(0x01), + /* + * all digits + */ + WIRE_VALID(0x01, '6', '1', '2', '0', '0', '0'), + /* + * non digit + */ + WIRE_INVALID(0x01, '+', '6', '1', '2', '0', '0', '0'), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_atma, sizeof(dns_rdata_in_atma_t)); +} + +/* AMTRELAY RDATA manipulations */ +ISC_RUN_TEST_IMPL(amtrelay) { + text_ok_t text_ok[] = { + TEXT_INVALID(""), TEXT_INVALID("0"), TEXT_INVALID("0 0"), + /* gateway type 0 */ + TEXT_VALID("0 0 0"), TEXT_VALID("0 1 0"), + TEXT_INVALID("0 2 0"), /* discovery out of range */ + TEXT_VALID("255 1 0"), /* max precedence */ + TEXT_INVALID("256 1 0"), /* precedence out of range */ + + /* IPv4 gateway */ + TEXT_INVALID("0 0 1"), /* no address */ + TEXT_VALID("0 0 1 0.0.0.0"), + TEXT_INVALID("0 0 1 0.0.0.0 x"), /* extra */ + TEXT_INVALID("0 0 1 0.0.0.0.0"), /* bad address */ + TEXT_INVALID("0 0 1 ::"), /* bad address */ + TEXT_INVALID("0 0 1 ."), /* bad address */ + + /* IPv6 gateway */ + TEXT_INVALID("0 0 2"), /* no address */ + TEXT_VALID("0 0 2 ::"), TEXT_INVALID("0 0 2 :: xx"), /* extra */ + TEXT_INVALID("0 0 2 0.0.0.0"), /* bad address */ + TEXT_INVALID("0 0 2 ."), /* bad address */ + + /* hostname gateway */ + TEXT_INVALID("0 0 3"), /* no name */ + /* IPv4 is a valid name */ + TEXT_VALID_CHANGED("0 0 3 0.0.0.0", "0 0 3 0.0.0.0."), + /* IPv6 is a valid name */ + TEXT_VALID_CHANGED("0 0 3 ::", "0 0 3 ::."), + TEXT_VALID_CHANGED("0 0 3 example", "0 0 3 example."), + TEXT_VALID("0 0 3 example."), + TEXT_INVALID("0 0 3 example. x"), /* extra */ + + /* unknown gateway */ + TEXT_VALID("\\# 2 0004"), TEXT_VALID("\\# 2 0084"), + TEXT_VALID("\\# 2 007F"), TEXT_VALID("\\# 3 000400"), + TEXT_VALID("\\# 3 008400"), TEXT_VALID("\\# 3 00FF00"), + + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + WIRE_INVALID(0x00), WIRE_VALID(0x00, 0x00), + WIRE_VALID(0x00, 0x80), WIRE_INVALID(0x00, 0x00, 0x00), + WIRE_INVALID(0x00, 0x80, 0x00), + + WIRE_INVALID(0x00, 0x01), WIRE_INVALID(0x00, 0x01, 0x00), + WIRE_INVALID(0x00, 0x01, 0x00, 0x00), + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x00), + WIRE_VALID(0x00, 0x01, 0x00, 0x00, 0x00, 0x00), + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00), + + WIRE_INVALID(0x00, 0x02), WIRE_INVALID(0x00, 0x02, 0x00), + WIRE_VALID(0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15), + WIRE_INVALID(0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16), + + WIRE_INVALID(0x00, 0x03), WIRE_VALID(0x00, 0x03, 0x00), + WIRE_INVALID(0x00, 0x03, 0x00, 0x00), /* extra */ + + WIRE_VALID(0x00, 0x04), WIRE_VALID(0x00, 0x04, 0x00), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_amtrelay, sizeof(dns_rdata_amtrelay_t)); +} + +ISC_RUN_TEST_IMPL(cdnskey) { + key_required(state, dns_rdatatype_cdnskey, sizeof(dns_rdata_cdnskey_t)); +} + +/* + * 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. + */ +ISC_RUN_TEST_IMPL(csync) { + 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() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_csync, sizeof(dns_rdata_csync_t)); +} + +ISC_RUN_TEST_IMPL(dnskey) { + key_required(state, dns_rdatatype_dnskey, sizeof(dns_rdata_dnskey_t)); +} + +/* + * DOA tests. + * + * draft-durand-doa-over-dns-03: + * + * 3.2. DOA RDATA Wire Format + * + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 0: | | + * | DOA-ENTERPRISE | + * | | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 4: | | + * | DOA-TYPE | + * | | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 8: | DOA-LOCATION | DOA-MEDIA-TYPE / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * 10: / / + * / DOA-MEDIA-TYPE (continued) / + * / / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * / / + * / DOA-DATA / + * / / + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * DOA-ENTERPRISE: a 32-bit unsigned integer in network order. + * + * DOA-TYPE: a 32-bit unsigned integer in network order. + * + * DOA-LOCATION: an 8-bit unsigned integer. + * + * DOA-MEDIA-TYPE: A <character-string> (see [RFC1035]). The first + * octet of the <character-string> contains the number of characters to + * follow. + * + * DOA-DATA: A variable length blob of binary data. The length of the + * DOA-DATA is not contained within the wire format of the RR and has to + * be computed from the RDLENGTH of the entire RR once other fields have + * been taken into account. + * + * 3.3. DOA RDATA Presentation Format + * + * The DOA-ENTERPRISE field is presented as an unsigned 32-bit decimal + * integer with range 0 - 4,294,967,295. + * + * The DOA-TYPE field is presented as an unsigned 32-bit decimal integer + * with range 0 - 4,294,967,295. + * + * The DOA-LOCATION field is presented as an unsigned 8-bit decimal + * integer with range 0 - 255. + * + * The DOA-MEDIA-TYPE field is presented as a single <character-string>. + * + * The DOA-DATA is presented as Base64 encoded data [RFC4648] unless the + * DOA-DATA is empty in which case it is presented as a single dash + * character ("-", ASCII 45). White space is permitted within Base64 + * data. + */ +ISC_RUN_TEST_IMPL(doa) { + text_ok_t text_ok[] = { + /* + * Valid, non-empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"text/plain\" Zm9v"), + /* + * Valid, non-empty DOA-DATA with whitespace in between. + */ + TEXT_VALID_CHANGED("0 0 1 \"text/plain\" Zm 9v", "0 0 1 " + "\"text/" + "plain\" " + "Zm9v"), + /* + * Valid, unquoted DOA-MEDIA-TYPE, non-empty DOA-DATA. + */ + TEXT_VALID_CHANGED("0 0 1 text/plain Zm9v", "0 0 1 " + "\"text/plain\" " + "Zm9v"), + /* + * Invalid, quoted non-empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\" \"Zm9v\""), + /* + * Valid, empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"text/plain\" -"), + /* + * Invalid, quoted empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\" \"-\""), + /* + * Invalid, missing "-" in empty DOA-DATA. + */ + TEXT_INVALID("0 0 1 \"text/plain\""), + /* + * Valid, undefined DOA-LOCATION. + */ + TEXT_VALID("0 0 100 \"text/plain\" Zm9v"), + /* + * Invalid, DOA-LOCATION too big. + */ + TEXT_INVALID("0 0 256 \"text/plain\" ZM9v"), + /* + * Valid, empty DOA-MEDIA-TYPE, non-empty DOA-DATA. + */ + TEXT_VALID("0 0 2 \"\" aHR0cHM6Ly93d3cuaXNjLm9yZy8="), + /* + * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA. + */ + TEXT_VALID("0 0 1 \"\" -"), + /* + * Valid, DOA-MEDIA-TYPE with a space. + */ + TEXT_VALID("0 0 1 \"plain text\" Zm9v"), + /* + * Invalid, missing DOA-MEDIA-TYPE. + */ + TEXT_INVALID("1234567890 1234567890 1"), + /* + * Valid, DOA-DATA over 255 octets. + */ + TEXT_VALID("1234567890 1234567890 1 \"image/gif\" " + "R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM" + "/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAA" + "AAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c" + "3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS" + "1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeF" + "AgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9" + "pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1" + "SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7"), + /* + * Invalid, bad Base64 in DOA-DATA. + */ + TEXT_INVALID("1234567890 1234567890 1 \"image/gif\" R0lGODl"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + /* + * Valid, empty DOA-MEDIA-TYPE, empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x01, + 0x00), + /* + * Invalid, missing DOA-MEDIA-TYPE. + */ + WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01), + /* + * Invalid, malformed DOA-MEDIA-TYPE length. + */ + WIRE_INVALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, + 0x01, 0xff), + /* + * Valid, empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x01, + 0x03, 0x66, 0x6f, 0x6f), + /* + * Valid, non-empty DOA-DATA. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x01, + 0x03, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72), + /* + * Valid, DOA-DATA over 255 octets. + */ + WIRE_VALID(0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x01, + 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x00, 0x66, + 0x99, 0xff, 0xff, 0xff, 0x33, 0x99, 0xcc, 0xcc, 0xff, + 0xff, 0x99, 0xcc, 0xff, 0x33, 0x66, 0x99, 0x66, 0xcc, + 0xff, 0x99, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x99, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x21, 0xf9, + 0x04, 0x01, 0x0a, 0x00, 0x0f, 0x00, 0x2c, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x19, 0x00, 0x00, 0x04, 0xc7, + 0xf0, 0x81, 0x49, 0x2b, 0x95, 0x36, 0x6b, 0x8d, 0xf7, + 0xec, 0x5e, 0x68, 0x81, 0x19, 0x29, 0x9e, 0x80, 0x89, + 0xae, 0x5c, 0xbb, 0x3e, 0xb0, 0x8a, 0xca, 0x1f, 0x1c, + 0xdc, 0x78, 0x00, 0x87, 0x34, 0xf7, 0xe4, 0xc0, 0xdb, + 0x6e, 0xd3, 0xbb, 0xfc, 0x82, 0x48, 0x1d, 0xb1, 0xa2, + 0x3a, 0x26, 0x93, 0xc5, 0x54, 0xe9, 0x49, 0x55, 0x96, + 0x2e, 0xa3, 0x6a, 0xd5, 0x45, 0x72, 0x6a, 0x93, 0x52, + 0xd7, 0x07, 0x77, 0x38, 0x0c, 0x6e, 0x83, 0x42, 0xe1, + 0x9c, 0x2b, 0x9b, 0x71, 0x58, 0x6c, 0xc7, 0x2b, 0x10, + 0x9c, 0xeb, 0x78, 0x01, 0x3a, 0x6f, 0xbf, 0x31, 0xe5, + 0x17, 0x39, 0x75, 0x03, 0x03, 0x83, 0x85, 0x67, 0x85, + 0x02, 0x04, 0x69, 0x7a, 0x7e, 0x7f, 0x52, 0x18, 0x5e, + 0x01, 0x83, 0x05, 0x75, 0x40, 0x78, 0x48, 0x57, 0x29, + 0x18, 0x41, 0x86, 0x75, 0x07, 0x82, 0x02, 0xa0, 0x41, + 0x2d, 0x3b, 0x92, 0x93, 0x7d, 0x04, 0x79, 0x77, 0x7d, + 0xa4, 0x4b, 0x00, 0x6c, 0xa1, 0xb1, 0x8c, 0x7a, 0x83, + 0x48, 0x4d, 0x12, 0xa7, 0xa8, 0xb1, 0x37, 0x83, 0x75, + 0x04, 0x99, 0x9b, 0x73, 0xb9, 0x48, 0x86, 0x6b, 0x01, + 0x89, 0xc8, 0x75, 0x6b, 0x03, 0xc0, 0x8e, 0x46, 0x35, + 0x49, 0x94, 0x7c, 0x6c, 0x95, 0xab, 0xcf, 0x7f, 0x36, + 0x48, 0x6a, 0x88, 0x05, 0x04, 0x05, 0x41, 0xde, 0x08, + 0xb1, 0x44, 0xda, 0x5f, 0xe7, 0x1e, 0xba, 0xe7, 0x4f, + 0x11, 0x00, 0x3b), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_doa, sizeof(dns_rdata_doa_t)); +} + +/* + * DS tests. + * + * RFC 4034: + * + * 5.1. DS RDATA Wire Format + * + * The RDATA for a DS RR consists of a 2 octet Key Tag field, a 1 octet + * Algorithm field, a 1 octet Digest Type field, and a Digest field. + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Key Tag | Algorithm | Digest Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / / + * / Digest / + * / / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 5.1.1. The Key Tag Field + * + * The Key Tag field lists the key tag of the DNSKEY RR referred to by + * the DS record, in network byte order. + * + * The Key Tag used by the DS RR is identical to the Key Tag used by + * RRSIG RRs. Appendix B describes how to compute a Key Tag. + * + * 5.1.2. The Algorithm Field + * + * The Algorithm field lists the algorithm number of the DNSKEY RR + * referred to by the DS record. + * + * The algorithm number used by the DS RR is identical to the algorithm + * number used by RRSIG and DNSKEY RRs. Appendix A.1 lists the + * algorithm number types. + * + * 5.1.3. The Digest Type Field + * + * The DS RR refers to a DNSKEY RR by including a digest of that DNSKEY + * RR. The Digest Type field identifies the algorithm used to construct + * the digest. Appendix A.2 lists the possible digest algorithm types. + * + * 5.1.4. The Digest Field + * + * The DS record refers to a DNSKEY RR by including a digest of that + * DNSKEY RR. + * + * The digest is calculated by concatenating the canonical form of the + * fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA, + * and then applying the digest algorithm. + * + * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); + * + * "|" denotes concatenation + * + * DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. + * + * The size of the digest may vary depending on the digest algorithm and + * DNSKEY RR size. As of the time of this writing, the only defined + * digest algorithm is SHA-1, which produces a 20 octet digest. + */ +ISC_RUN_TEST_IMPL(ds) { + text_ok_t text_ok[] = { + /* + * Invalid, empty record. + */ + TEXT_INVALID(""), + /* + * Invalid, no algorithm. + */ + TEXT_INVALID("0"), + /* + * Invalid, no digest type. + */ + TEXT_INVALID("0 0"), + /* + * Invalid, no digest. + */ + TEXT_INVALID("0 0 0"), + /* + * Valid, 1-octet digest for a reserved digest type. + */ + TEXT_VALID("0 0 0 00"), + /* + * Invalid, short SHA-1 digest. + */ + TEXT_INVALID("0 0 1 00"), + TEXT_INVALID("0 0 1 4FDCE83016EDD29077621FE568F8DADDB5809B"), + /* + * Valid, 20-octet SHA-1 digest. + */ + TEXT_VALID("0 0 1 4FDCE83016EDD29077621FE568F8DADDB5809B6A"), + /* + * Invalid, excessively long SHA-1 digest. + */ + TEXT_INVALID("0 0 1 4FDCE83016EDD29077621FE568F8DADDB5809B" + "6A00"), + /* + * Invalid, short SHA-256 digest. + */ + TEXT_INVALID("0 0 2 00"), + TEXT_INVALID("0 0 2 D001BD422FFDA9B745425B71DC17D007E69186" + "9BD59C5F237D9BF85434C313"), + /* + * Valid, 32-octet SHA-256 digest. + */ + TEXT_VALID_CHANGED("0 0 2 " + "D001BD422FFDA9B745425B71DC17D007E691869B" + "D59C5F237D9BF85434C3133F", + "0 0 2 " + "D001BD422FFDA9B745425B71DC17D007E691869B" + "D59C5F237D9BF854 34C3133F"), + /* + * Invalid, excessively long SHA-256 digest. + */ + TEXT_INVALID("0 0 2 D001BD422FFDA9B745425B71DC17D007E69186" + "9BD59C5F237D9BF85434C3133F00"), + /* + * Valid, GOST is no longer supported, hence no length checks. + */ + TEXT_VALID("0 0 3 00"), + /* + * Invalid, short SHA-384 digest. + */ + TEXT_INVALID("0 0 4 00"), + TEXT_INVALID("0 0 4 AC748D6C5AA652904A8763D64B7DFFFFA98152" + "BE12128D238BEBB4814B648F5A841E15CAA2DE348891" + "A37A699F65E5"), + /* + * Valid, 48-octet SHA-384 digest. + */ + TEXT_VALID_CHANGED("0 0 4 " + "AC748D6C5AA652904A8763D64B7DFFFFA98152BE" + "12128D238BEBB4814B648F5A841E15CAA2DE348891A" + "37A" + "699F65E54D", + "0 0 4 " + "AC748D6C5AA652904A8763D64B7DFFFFA98152BE" + "12128D238BEBB481 " + "4B648F5A841E15CAA2DE348891A37A" + "699F65E54D"), + /* + * Invalid, excessively long SHA-384 digest. + */ + TEXT_INVALID("0 0 4 AC748D6C5AA652904A8763D64B7DFFFFA98152" + "BE12128D238BEBB4814B648F5A841E15CAA2DE348891" + "A37A699F65E54D00"), + /* + * Valid, 1-octet digest for an unassigned digest type. + */ + TEXT_VALID("0 0 5 00"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { + /* + * Invalid, truncated key tag. + */ + WIRE_INVALID(0x00), + /* + * Invalid, no algorithm. + */ + WIRE_INVALID(0x00, 0x00), + /* + * Invalid, no digest type. + */ + WIRE_INVALID(0x00, 0x00, 0x00), + /* + * Invalid, no digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00), + /* + * Valid, 1-octet digest for a reserved digest type. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Invalid, short SHA-1 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x01, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00, 0x01, 0x4F, 0xDC, 0xE8, 0x30, + 0x16, 0xED, 0xD2, 0x90, 0x77, 0x62, 0x1F, 0xE5, + 0x68, 0xF8, 0xDA, 0xDD, 0xB5, 0x80, 0x9B), + /* + * Valid, 20-octet SHA-1 digest. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x01, 0x4F, 0xDC, 0xE8, 0x30, 0x16, + 0xED, 0xD2, 0x90, 0x77, 0x62, 0x1F, 0xE5, 0x68, 0xF8, + 0xDA, 0xDD, 0xB5, 0x80, 0x9B, 0x6A), + /* + * Invalid, excessively long SHA-1 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x01, 0x4F, 0xDC, 0xE8, 0x30, + 0x16, 0xED, 0xD2, 0x90, 0x77, 0x62, 0x1F, 0xE5, + 0x68, 0xF8, 0xDA, 0xDD, 0xB5, 0x80, 0x9B, 0x6A, + 0x00), + /* + * Invalid, short SHA-256 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x02, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00, 0x02, 0xD0, 0x01, 0xBD, 0x42, + 0x2F, 0xFD, 0xA9, 0xB7, 0x45, 0x42, 0x5B, 0x71, + 0xDC, 0x17, 0xD0, 0x07, 0xE6, 0x91, 0x86, 0x9B, + 0xD5, 0x9C, 0x5F, 0x23, 0x7D, 0x9B, 0xF8, 0x54, + 0x34, 0xC3, 0x13), + /* + * Valid, 32-octet SHA-256 digest. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x02, 0xD0, 0x01, 0xBD, 0x42, 0x2F, + 0xFD, 0xA9, 0xB7, 0x45, 0x42, 0x5B, 0x71, 0xDC, 0x17, + 0xD0, 0x07, 0xE6, 0x91, 0x86, 0x9B, 0xD5, 0x9C, 0x5F, + 0x23, 0x7D, 0x9B, 0xF8, 0x54, 0x34, 0xC3, 0x13, + 0x3F), + /* + * Invalid, excessively long SHA-256 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x02, 0xD0, 0x01, 0xBD, 0x42, + 0x2F, 0xFD, 0xA9, 0xB7, 0x45, 0x42, 0x5B, 0x71, + 0xDC, 0x17, 0xD0, 0x07, 0xE6, 0x91, 0x86, 0x9B, + 0xD5, 0x9C, 0x5F, 0x23, 0x7D, 0x9B, 0xF8, 0x54, + 0x34, 0xC3, 0x13, 0x3F, 0x00), + /* + * Valid, GOST is no longer supported, hence no length checks. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x03, 0x00), + /* + * Invalid, short SHA-384 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x04, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00, 0x04, 0xAC, 0x74, 0x8D, 0x6C, + 0x5A, 0xA6, 0x52, 0x90, 0x4A, 0x87, 0x63, 0xD6, + 0x4B, 0x7D, 0xFF, 0xFF, 0xA9, 0x81, 0x52, 0xBE, + 0x12, 0x12, 0x8D, 0x23, 0x8B, 0xEB, 0xB4, 0x81, + 0x4B, 0x64, 0x8F, 0x5A, 0x84, 0x1E, 0x15, 0xCA, + 0xA2, 0xDE, 0x34, 0x88, 0x91, 0xA3, 0x7A, 0x69, + 0x9F, 0x65, 0xE5), + /* + * Valid, 48-octet SHA-384 digest. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x04, 0xAC, 0x74, 0x8D, 0x6C, 0x5A, + 0xA6, 0x52, 0x90, 0x4A, 0x87, 0x63, 0xD6, 0x4B, 0x7D, + 0xFF, 0xFF, 0xA9, 0x81, 0x52, 0xBE, 0x12, 0x12, 0x8D, + 0x23, 0x8B, 0xEB, 0xB4, 0x81, 0x4B, 0x64, 0x8F, 0x5A, + 0x84, 0x1E, 0x15, 0xCA, 0xA2, 0xDE, 0x34, 0x88, 0x91, + 0xA3, 0x7A, 0x69, 0x9F, 0x65, 0xE5, 0x4D), + /* + * Invalid, excessively long SHA-384 digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x04, 0xAC, 0x74, 0x8D, 0x6C, + 0x5A, 0xA6, 0x52, 0x90, 0x4A, 0x87, 0x63, 0xD6, + 0x4B, 0x7D, 0xFF, 0xFF, 0xA9, 0x81, 0x52, 0xBE, + 0x12, 0x12, 0x8D, 0x23, 0x8B, 0xEB, 0xB4, 0x81, + 0x4B, 0x64, 0x8F, 0x5A, 0x84, 0x1E, 0x15, 0xCA, + 0xA2, 0xDE, 0x34, 0x88, 0x91, 0xA3, 0x7A, 0x69, + 0x9F, 0x65, 0xE5, 0x4D, 0x00), + WIRE_VALID(0x00, 0x00, 0x04, 0x00, 0x00), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_ds, sizeof(dns_rdata_ds_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). + */ +ISC_RUN_TEST_IMPL(edns_client_subnet) { + 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() + }; + + check_rdata(NULL, wire_ok, NULL, true, dns_rdataclass_in, + dns_rdatatype_opt, sizeof(dns_rdata_opt_t)); +} + +/* + * http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt + * + * The RDATA portion of both the NIMLOC and EID records contains + * uninterpreted binary data. The representation in the text master file + * is an even number of hex characters (0 to 9, a to f), case is not + * significant. For readability, whitespace may be included in the value + * field and should be ignored when reading a master file. + */ +ISC_RUN_TEST_IMPL(eid) { + text_ok_t text_ok[] = { TEXT_VALID("AABBCC"), + TEXT_VALID_CHANGED("AA bb cc", "AABBCC"), + TEXT_INVALID("aab"), + /* + * Sentinel. + */ + TEXT_SENTINEL() }; + wire_ok_t wire_ok[] = { WIRE_VALID(0x00), WIRE_VALID(0xAA, 0xBB, 0xCC), + /* + * Sentinel. + */ + WIRE_SENTINEL() }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_eid, sizeof(dns_rdata_in_eid_t)); +} + +/* + * test that an oversized HIP record will be rejected + */ +ISC_RUN_TEST_IMPL(hip) { + text_ok_t text_ok[] = { + /* RFC 8005 examples. */ + TEXT_VALID_LOOP(0, "2 200100107B1A74DF365639CC39F1D578 " + "AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cI" + "vM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbW" + "Iy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+b" + "SRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWx" + "Z48AWkskmdHaVDP4BcelrTI3rMXdXF5D"), + TEXT_VALID_LOOP(1, "2 200100107B1A74DF365639CC39F1D578 " + "AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cI" + "vM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbW" + "Iy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+b" + "SRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWx" + "Z48AWkskmdHaVDP4BcelrTI3rMXdXF5D " + "rvs1.example.com."), + TEXT_VALID_LOOP(2, "2 200100107B1A74DF365639CC39F1D578 " + "AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cI" + "vM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbW" + "Iy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+b" + "SRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWx" + "Z48AWkskmdHaVDP4BcelrTI3rMXdXF5D " + "rvs1.example.com. rvs2.example.com."), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + unsigned char hipwire[DNS_RDATA_MAXLENGTH] = { 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0x41, + 0x42, 0x43, 0x44, 0x00 }; + unsigned char buf[1024 * 1024]; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_result_t result; + size_t i; + + /* + * Fill the rest of input buffer with compression pointers. + */ + for (i = 12; i < sizeof(hipwire) - 2; i += 2) { + hipwire[i] = 0xc0; + hipwire[i + 1] = 0x06; + } + + result = wire_to_rdata(hipwire, sizeof(hipwire), dns_rdataclass_in, + dns_rdatatype_hip, buf, sizeof(buf), &rdata); + assert_int_equal(result, DNS_R_FORMERR); + check_text_ok(text_ok, dns_rdataclass_in, dns_rdatatype_hip, + sizeof(dns_rdata_hip_t)); +} + +/* + * 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. + */ +ISC_RUN_TEST_IMPL(isdn) { + 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() + }; + + check_rdata(NULL, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_isdn, sizeof(dns_rdata_isdn_t)); +} + +/* + * KEY tests. + */ +ISC_RUN_TEST_IMPL(key) { + wire_ok_t wire_ok[] = { /* + * RDATA is comprised of: + * + * - 2 octets for Flags, + * - 1 octet for Protocol, + * - 1 octet for Algorithm, + * - variable number of octets for Public Key. + * + * RFC 2535 section 3.1.2 states that if bits + * 0-1 of Flags are both set, the RR stops after + * the algorithm octet and thus its length must + * be 4 octets. In any other case, though, the + * Public Key part must not be empty. + */ + WIRE_INVALID(0x00), + WIRE_INVALID(0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00), + WIRE_VALID(0xc0, 0x00, 0x00, 0x00), + WIRE_INVALID(0xc0, 0x00, 0x00, 0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00, 0x00), + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00), + WIRE_SENTINEL() + }; + + check_rdata(NULL, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_key, sizeof(dns_rdata_key_t)); +} + +/* + * LOC tests. + */ +ISC_RUN_TEST_IMPL(loc) { + text_ok_t text_ok[] = { + TEXT_VALID_CHANGED("0 N 0 E 0", "0 0 0.000 N 0 0 0.000 E 0.00m " + "1m 10000m 10m"), + TEXT_VALID_CHANGED("0 S 0 W 0", "0 0 0.000 N 0 0 0.000 E 0.00m " + "1m 10000m 10m"), + TEXT_VALID_CHANGED("0 0 N 0 0 E 0", "0 0 0.000 N 0 0 0.000 E " + "0.00m 1m 10000m 10m"), + TEXT_VALID_CHANGED("0 0 0 N 0 0 0 E 0", + "0 0 0.000 N 0 0 0.000 E 0.00m 1m 10000m " + "10m"), + TEXT_VALID_CHANGED("0 0 0 N 0 0 0 E 0", + "0 0 0.000 N 0 0 0.000 E 0.00m 1m 10000m " + "10m"), + TEXT_VALID_CHANGED("0 0 0. N 0 0 0. E 0", + "0 0 0.000 N 0 0 0.000 E 0.00m 1m 10000m " + "10m"), + TEXT_VALID_CHANGED("0 0 .0 N 0 0 .0 E 0", + "0 0 0.000 N 0 0 0.000 E 0.00m 1m 10000m " + "10m"), + TEXT_INVALID("0 North 0 East 0"), + TEXT_INVALID("0 South 0 West 0"), + TEXT_INVALID("0 0 . N 0 0 0. E 0"), + TEXT_INVALID("0 0 0. N 0 0 . E 0"), + TEXT_INVALID("0 0 0. N 0 0 0. E m"), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 ."), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 m"), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 0 ."), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 0 m"), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 0 0 ."), + TEXT_INVALID("0 0 0. N 0 0 0. E 0 0 0 m"), + TEXT_VALID_CHANGED("90 N 180 E 0", "90 0 0.000 N 180 0 0.000 E " + "0.00m 1m 10000m 10m"), + TEXT_INVALID("90 1 N 180 E 0"), + TEXT_INVALID("90 0 1 N 180 E 0"), + TEXT_INVALID("90 N 180 1 E 0"), + TEXT_INVALID("90 N 180 0 1 E 0"), + TEXT_VALID_CHANGED("90 S 180 W 0", "90 0 0.000 S 180 0 0.000 W " + "0.00m 1m 10000m 10m"), + TEXT_INVALID("90 1 S 180 W 0"), + TEXT_INVALID("90 0 1 S 180 W 0"), + TEXT_INVALID("90 S 180 1 W 0"), + TEXT_INVALID("90 S 180 0 1 W 0"), + TEXT_INVALID("0 0 0.000 E 0 0 0.000 E -0.95m 1m 10000m 10m"), + TEXT_VALID("0 0 0.000 N 0 0 0.000 E -0.95m 1m 10000m 10m"), + TEXT_VALID("0 0 0.000 N 0 0 0.000 E -0.05m 1m 10000m 10m"), + TEXT_VALID("0 0 0.000 N 0 0 0.000 E -100000.00m 1m 10000m 10m"), + TEXT_VALID("0 0 0.000 N 0 0 0.000 E 42849672.95m 1m 10000m " + "10m"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + + check_rdata(text_ok, 0, NULL, false, dns_rdataclass_in, + dns_rdatatype_loc, sizeof(dns_rdata_loc_t)); +} + +/* + * http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt + * + * The RDATA portion of both the NIMLOC and EID records contains + * uninterpreted binary data. The representation in the text master file + * is an even number of hex characters (0 to 9, a to f), case is not + * significant. For readability, whitespace may be included in the value + * field and should be ignored when reading a master file. + */ +ISC_RUN_TEST_IMPL(nimloc) { + text_ok_t text_ok[] = { TEXT_VALID("AABBCC"), + TEXT_VALID_CHANGED("AA bb cc", "AABBCC"), + TEXT_INVALID("aab"), + /* + * Sentinel. + */ + TEXT_SENTINEL() }; + wire_ok_t wire_ok[] = { WIRE_VALID(0x00), WIRE_VALID(0xAA, 0xBB, 0xCC), + /* + * Sentinel. + */ + WIRE_SENTINEL() }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_nimloc, sizeof(dns_rdata_in_nimloc_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. + */ +ISC_RUN_TEST_IMPL(nsec) { + text_ok_t text_ok[] = { TEXT_INVALID(""), TEXT_INVALID("."), + TEXT_VALID(". RRSIG"), TEXT_SENTINEL() }; + wire_ok_t wire_ok[] = { WIRE_INVALID(0x00), WIRE_INVALID(0x00, 0x00), + WIRE_INVALID(0x00, 0x00, 0x00), + WIRE_VALID(0x00, 0x00, 0x01, 0x02), + WIRE_SENTINEL() }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_nsec, sizeof(dns_rdata_nsec_t)); +} + +/* + * NSEC3 tests. + * + * RFC 5155. + */ +ISC_RUN_TEST_IMPL(nsec3) { + text_ok_t text_ok[] = { TEXT_INVALID(""), + TEXT_INVALID("."), + TEXT_INVALID(". RRSIG"), + TEXT_INVALID("1 0 10 76931F"), + TEXT_INVALID("1 0 10 76931F " + "IMQ912BREQP1POLAH3RMONG&" + "UED541AS"), + TEXT_INVALID("1 0 10 76931F " + "IMQ912BREQP1POLAH3RMONGAUED541AS " + "A RRSIG BADTYPE"), + TEXT_VALID("1 0 10 76931F " + "AJHVGTICN6K0VDA53GCHFMT219SRRQLM A " + "RRSIG"), + TEXT_VALID("1 0 10 76931F " + "AJHVGTICN6K0VDA53GCHFMT219SRRQLM"), + TEXT_VALID("1 0 10 - " + "AJHVGTICN6K0VDA53GCHFMT219SRRQLM"), + TEXT_SENTINEL() }; + + check_rdata(text_ok, NULL, NULL, false, dns_rdataclass_in, + dns_rdatatype_nsec3, sizeof(dns_rdata_nsec3_t)); +} + +/* NXT RDATA manipulations */ +ISC_RUN_TEST_IMPL(nxt) { + compare_ok_t compare_ok[] = { + COMPARE("a. A SIG", "a. A SIG", 0), + /* + * Records that differ only in the case of the next + * name should be equal. + */ + COMPARE("A. A SIG", "a. A SIG", 0), + /* + * Sorting on name field. + */ + COMPARE("A. A SIG", "b. A SIG", -1), + COMPARE("b. A SIG", "A. A SIG", 1), + /* bit map differs */ + COMPARE("b. A SIG", "b. A AAAA SIG", -1), + /* order of bit map does not matter */ + COMPARE("b. A SIG AAAA", "b. A AAAA SIG", 0), COMPARE_SENTINEL() + }; + + check_rdata(NULL, NULL, compare_ok, false, dns_rdataclass_in, + dns_rdatatype_nxt, sizeof(dns_rdata_nxt_t)); +} + +ISC_RUN_TEST_IMPL(rkey) { + text_ok_t text_ok[] = { /* + * Valid, flags set to 0 and a key is present. + */ + TEXT_VALID("0 0 0 aaaa"), + /* + * Invalid, non-zero flags. + */ + TEXT_INVALID("1 0 0 aaaa"), + TEXT_INVALID("65535 0 0 aaaa"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + wire_ok_t wire_ok[] = { /* + * Valid, flags set to 0 and a key is present. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Invalid, non-zero flags. + */ + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x00), + WIRE_INVALID(0xff, 0xff, 0x00, 0x00, 0x00), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + key_required(state, dns_rdatatype_rkey, sizeof(dns_rdata_rkey_t)); + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_rkey, sizeof(dns_rdata_rkey_t)); +} + +/* SSHFP RDATA manipulations */ +ISC_RUN_TEST_IMPL(sshfp) { + text_ok_t text_ok[] = { TEXT_INVALID(""), /* too short */ + TEXT_INVALID("0"), /* reserved, too short */ + TEXT_VALID("0 0"), /* no finger print */ + TEXT_VALID("0 0 AA"), /* reserved */ + TEXT_INVALID("0 1 AA"), /* too short SHA 1 + * digest */ + TEXT_INVALID("0 2 AA"), /* too short SHA 256 + * digest */ + TEXT_VALID("0 3 AA"), /* unknown finger print + * type */ + /* good length SHA 1 digest */ + TEXT_VALID("1 1 " + "00112233445566778899AABBCCDDEEFF171" + "81920"), + /* good length SHA 256 digest */ + TEXT_VALID("4 2 " + "A87F1B687AC0E57D2A081A2F282672334D9" + "0ED316D2B818CA9580EA3 84D92401"), + /* + * totext splits the fingerprint into chunks and + * emits uppercase hex. + */ + TEXT_VALID_CHANGED("1 2 " + "00112233445566778899aabbccd" + "deeff " + "00112233445566778899AABBCCD" + "DEEFF", + "1 2 " + "00112233445566778899AABBCCD" + "DEEFF" + "00112233445566778899AABB " + "CCDDEEFF"), + TEXT_SENTINEL() }; + wire_ok_t wire_ok[] = { + WIRE_INVALID(0x00), /* reserved too short */ + WIRE_VALID(0x00, 0x00), /* reserved no finger print */ + WIRE_VALID(0x00, 0x00, 0x00), /* reserved */ + + /* too short SHA 1 digests */ + WIRE_INVALID(0x00, 0x01), WIRE_INVALID(0x00, 0x01, 0x00), + WIRE_INVALID(0x00, 0x01, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x17, 0x18, 0x19), + /* good length SHA 1 digest */ + WIRE_VALID(0x00, 0x01, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x17, 0x18, 0x19, 0x20), + /* too long SHA 1 digest */ + WIRE_INVALID(0x00, 0x01, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x17, 0x18, 0x19, 0x20, 0x21), + /* too short SHA 256 digests */ + WIRE_INVALID(0x00, 0x02), WIRE_INVALID(0x00, 0x02, 0x00), + WIRE_INVALID(0x00, 0x02, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, + 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, + 0x31), + /* good length SHA 256 digest */ + WIRE_VALID(0x00, 0x02, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32), + /* too long SHA 256 digest */ + WIRE_INVALID(0x00, 0x02, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, + 0xEE, 0xFF, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, + 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, + 0x31, 0x32, 0x33), + /* unknown digest, * no fingerprint */ + WIRE_VALID(0x00, 0x03), WIRE_VALID(0x00, 0x03, 0x00), /* unknown + * digest + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_sshfp, sizeof(dns_rdata_sshfp_t)); +} + +/* + * WKS tests. + * + * RFC 1035: + * + * 3.4.2. WKS RDATA format + * + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ADDRESS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | PROTOCOL | | + * +--+--+--+--+--+--+--+--+ | + * | | + * / <BIT MAP> / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * where: + * + * ADDRESS An 32 bit Internet address + * + * PROTOCOL An 8 bit IP protocol number + * + * <BIT MAP> A variable length bit map. The bit map must be a + * multiple of 8 bits long. + * + * The WKS record is used to describe the well known services supported by + * a particular protocol on a particular internet address. The PROTOCOL + * field specifies an IP protocol number, and the bit map has one bit per + * port of the specified protocol. The first bit corresponds to port 0, + * the second to port 1, etc. If the bit map does not include a bit for a + * protocol of interest, that bit is assumed zero. The appropriate values + * and mnemonics for ports and protocols are specified in [RFC-1010]. + * + * For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port + * 25 (SMTP). If this bit is set, a SMTP server should be listening on TCP + * port 25; if zero, SMTP service is not supported on the specified + * address. + */ +ISC_RUN_TEST_IMPL(wks) { + text_ok_t text_ok[] = { /* + * Valid, IPv4 address in dotted-quad form. + */ + TEXT_VALID("127.0.0.1 6"), + /* + * Invalid, IPv4 address not in dotted-quad + * form. + */ + TEXT_INVALID("127.1 6"), + /* + * Sentinel. + */ + TEXT_SENTINEL() + }; + 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() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_wks, sizeof(dns_rdata_in_wks_t)); +} + +ISC_RUN_TEST_IMPL(https_svcb) { + /* + * Known keys: mandatory, apln, no-default-alpn, port, + * ipv4hint, port, ipv6hint, dohpath. + */ + text_ok_t text_ok[] = { + /* unknown key invalid */ + TEXT_INVALID("1 . unknown="), + /* no domain */ + TEXT_INVALID("0"), + /* minimal record */ + TEXT_VALID_LOOP(0, "0 ."), + /* Alias form requires SvcFieldValue to be empty */ + TEXT_INVALID("0 . alpn=\"h2\""), + /* no "key" prefix */ + TEXT_INVALID("2 svc.example.net. 0=\"2222\""), + /* no key value */ + TEXT_INVALID("2 svc.example.net. key"), + /* no key value */ + TEXT_INVALID("2 svc.example.net. key=\"2222\""), + /* zero pad invalid */ + TEXT_INVALID("2 svc.example.net. key07=\"2222\""), + TEXT_VALID_LOOP(1, "2 svc.example.net. key8=\"2222\""), + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. key8=2222", + "2 svc.example.net. key8=\"2222\""), + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h2", + "2 svc.example.net. alpn=\"h2\""), + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h3", + "2 svc.example.net. alpn=\"h3\""), + /* alpn has 2 sub field "h2" and "h3" */ + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h2,h3", + "2 svc.example.net. alpn=\"h2,h3\""), + /* apln has 2 sub fields "h1,h2" and "h3" (comma escaped) */ + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. alpn=h1\\\\,h2,h3", + "2 svc.example.net. alpn=\"h1\\\\,h2,h3\""), + TEXT_VALID_LOOP(1, "2 svc.example.net. port=50"), + /* no-default-alpn, alpn is required */ + TEXT_INVALID("2 svc.example.net. no-default-alpn"), + /* no-default-alpn with alpn present */ + TEXT_VALID_LOOPCHG( + 2, "2 svc.example.net. no-default-alpn alpn=h2", + "2 svc.example.net. alpn=\"h2\" no-default-alpn"), + /* empty hint */ + TEXT_INVALID("2 svc.example.net. ipv4hint="), + TEXT_VALID_LOOP(1, "2 svc.example.net. " + "ipv4hint=10.50.0.1,10.50.0.2"), + /* empty hint */ + TEXT_INVALID("2 svc.example.net. ipv6hint="), + TEXT_VALID_LOOP(1, "2 svc.example.net. ipv6hint=::1,2002::1"), + TEXT_VALID_LOOP(1, "2 svc.example.net. ech=abcdefghijkl"), + /* bad base64 */ + TEXT_INVALID("2 svc.example.net. ech=abcdefghijklm"), + TEXT_VALID_LOOP(1, "2 svc.example.net. key8=\"2222\""), + /* Out of key order on input (alpn == key1). */ + TEXT_VALID_LOOPCHG(2, + "2 svc.example.net. key8=\"2222\" alpn=h2", + "2 svc.example.net. alpn=\"h2\" " + "key8=\"2222\""), + TEXT_VALID_LOOP(1, "2 svc.example.net. key65535=\"2222\""), + TEXT_INVALID("2 svc.example.net. key65536=\"2222\""), + TEXT_VALID_LOOP(1, "2 svc.example.net. key10"), + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. key11=", + "2 svc.example.net. key11"), + TEXT_VALID_LOOPCHG(1, "2 svc.example.net. key12=\"\"", + "2 svc.example.net. key12"), + /* empty alpn-id sub fields */ + TEXT_INVALID("2 svc.example.net. alpn"), + TEXT_INVALID("2 svc.example.net. alpn="), + TEXT_INVALID("2 svc.example.net. alpn=,h1"), + TEXT_INVALID("2 svc.example.net. alpn=h1,"), + TEXT_INVALID("2 svc.example.net. alpn=h1,,h2"), + /* mandatory */ + TEXT_VALID_LOOP(2, "2 svc.example.net. mandatory=alpn " + "alpn=\"h2\""), + TEXT_VALID_LOOP(3, "2 svc.example.net. mandatory=alpn,port " + "alpn=\"h2\" port=443"), + TEXT_VALID_LOOPCHG(3, + "2 svc.example.net. mandatory=port,alpn " + "alpn=\"h2\" port=443", + "2 svc.example.net. mandatory=alpn,port " + "alpn=\"h2\" port=443"), + TEXT_INVALID("2 svc.example.net. mandatory=mandatory"), + TEXT_INVALID("2 svc.example.net. mandatory=port"), + TEXT_INVALID("2 svc.example.net. mandatory=,port port=433"), + TEXT_INVALID("2 svc.example.net. mandatory=port, port=433"), + TEXT_INVALID("2 svc.example.net. " + "mandatory=alpn,,port alpn=h2 port=433"), + /* mandatory w/ unknown key values */ + TEXT_VALID_LOOP(2, "2 svc.example.net. mandatory=key8 key8"), + TEXT_VALID_LOOP(3, "2 svc.example.net. mandatory=key8,key9 " + "key8 key9"), + TEXT_VALID_LOOPCHG( + 3, "2 svc.example.net. mandatory=key9,key8 key8 key9", + "2 svc.example.net. mandatory=key8,key9 key8 key9"), + TEXT_INVALID("2 svc.example.net. " + "mandatory=key8,key8"), + TEXT_INVALID("2 svc.example.net. mandatory=,key8"), + TEXT_INVALID("2 svc.example.net. mandatory=key8,"), + TEXT_INVALID("2 svc.example.net. " + "mandatory=key8,,key8"), + /* Invalid test vectors */ + TEXT_INVALID("1 foo.example.com. ( key123=abc key123=def )"), + TEXT_INVALID("1 foo.example.com. mandatory"), + TEXT_INVALID("1 foo.example.com. alpn"), + TEXT_INVALID("1 foo.example.com. port"), + TEXT_INVALID("1 foo.example.com. ipv4hint"), + TEXT_INVALID("1 foo.example.com. ipv6hint"), + TEXT_INVALID("1 foo.example.com. no-default-alpn=abc"), + TEXT_INVALID("1 foo.example.com. mandatory=key123"), + TEXT_INVALID("1 foo.example.com. mandatory=mandatory"), + TEXT_INVALID("1 foo.example.com. ( mandatory=key123,key123 " + "key123=abc)"), + /* dohpath tests */ + TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{?dns}", + "1 example.net. key7=\"/{?dns}\""), + TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/some/path{?dns}", + "1 example.net. key7=\"/some/path{?dns}\""), + TEXT_INVALID("1 example.com. dohpath=no-slash"), + TEXT_INVALID("1 example.com. dohpath=/{?notdns}"), + TEXT_INVALID("1 example.com. dohpath=/notvariable"), + TEXT_SENTINEL() + + }; + wire_ok_t wire_ok[] = { + /* + * Too short + */ + WIRE_INVALID(0x00, 0x00), + /* + * Minimal length record. + */ + WIRE_VALID(0x00, 0x00, 0x00), + /* + * Alias with non-empty SvcFieldValue (key7=""). + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00), + /* + * Bad key7= length (longer than rdata). + */ + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x01), + /* + * Port (0x03) too small (zero and one octets). + */ + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00), + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00), + /* Valid port */ + WIRE_VALID_LOOP(1, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x02, + 0x00, 0x00), + /* + * Port (0x03) too big (three octets). + */ + WIRE_INVALID(0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x00, 0x00), + /* + * Duplicate keys. + */ + WIRE_INVALID(0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00), + /* + * Out of order keys. + */ + WIRE_INVALID(0x01, 0x01, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00), + /* + * Empty of mandatory key list. + */ + WIRE_INVALID(0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00), + /* + * "mandatory=mandatory" is invalid + */ + WIRE_INVALID(0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00), + /* + * Out of order mandatory key list. + */ + WIRE_INVALID(0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x80, 0x00, 0x71, 0x00, 0x71, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00), + /* + * Alpn(0x00 0x01) (length 0x00 0x09) "h1,h2" + "h3" + */ + WIRE_VALID_LOOP(0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x09, + 5, 'h', '1', ',', 'h', '2', 2, 'h', '3'), + /* + * Alpn(0x00 0x01) (length 0x00 0x09) "h1\h2" + "h3" + */ + WIRE_VALID_LOOP(0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x09, + 5, 'h', '1', '\\', 'h', '2', 2, 'h', '3'), + /* + * no-default-alpn (0x00 0x02) without alpn, alpn is required. + */ + WIRE_INVALID(0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00), + /* + * Alpn(0x00 0x01) with zero length elements is invalid + */ + WIRE_INVALID(0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00), + WIRE_SENTINEL() + }; + /* Test vectors from RFCXXXX */ + textvsunknown_t textvsunknown[] = { + /* AliasForm */ + { "0 foo.example.com", "\\# 19 ( 00 00 03 66 6f 6f 07 65 78 61 " + "6d 70 6c 65 03 63 6f 6d 00)" }, + /* ServiceForm */ + { "1 .", "\\# 3 ( 00 01 00)" }, + /* Port example */ + { "16 foo.example.com port=53", + "\\# 25 ( 00 10 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f " + "6d 00 00 03 00 02 00 35 )" }, + /* Unregistered keys with unquoted value. */ + { "1 foo.example.com key667=hello", + "\\# 28 ( 00 01 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f " + "6d 00 02 9b 00 05 68 65 6c 6c 6f )" }, + /* + * Quoted decimal-escaped character. + * 1 foo.example.com key667="hello\210qoo" + */ + { "1 foo.example.com key667=\"hello\\210qoo\"", + "\\# 32 ( 00 01 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f " + "6d 00 02 9b 00 09 68 65 6c 6c 6f d2 71 6f 6f )" }, + /* + * IPv6 hints example, quoted. + * 1 foo.example.com ipv6hint="2001:db8::1,2001:db8::53:1" + */ + { "1 foo.example.com ipv6hint=\"2001:db8::1,2001:db8::53:1\"", + "\\# 55 ( 00 01 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f " + "6d 00 00 06 00 20 20 01 0d b8 00 00 00 00 00 00 00 00 00 00 " + "00 01 20 01 0d b8 00 00 00 00 00 00 00 00 00 53 00 01 )" }, + /* SvcParamValues and mandatory out of order. */ + { "16 foo.example.org alpn=h2,h3-19 mandatory=ipv4hint,alpn " + "ipv4hint=192.0.2.1", + "\\# 48 ( 00 10 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 6f 72 " + "67 00 00 00 00 04 00 01 00 04 00 01 00 09 02 68 32 05 68 33 " + "2d 31 39 00 04 00 04 c0 00 02 01 )" }, + /* + * Quoted ALPN with escaped comma and backslash. + * 16 foo.example.org alpn="f\\\\oo\\,bar,h2" + */ + { "16 foo.example.org alpn=\"f\\\\\\\\oo\\\\,bar,h2\"", + "\\# 35 ( 00 10 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 6f 72 " + "67 00 00 01 00 0c 08 66 5c 6f 6f 2c 62 61 72 02 68 32 )" }, + /* + * Unquoted ALPN with escaped comma and backslash. + * 16 foo.example.org alpn=f\\\092oo\092,bar,h2 + */ + { "16 foo.example.org alpn=f\\\\\\092oo\\092,bar,h2", + "\\# 35 ( 00 10 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 6f 72 " + "67 00 00 01 00 0c 08 66 5c 6f 6f 2c 62 61 72 02 68 32 )" }, + { NULL, NULL } + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_svcb, sizeof(dns_rdata_in_svcb_t)); + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_https, sizeof(dns_rdata_in_https_t)); + + check_textvsunknown(textvsunknown, dns_rdataclass_in, + dns_rdatatype_svcb); + check_textvsunknown(textvsunknown, dns_rdataclass_in, + dns_rdatatype_https); +} + +/* + * ZONEMD tests. + * + * Excerpted from RFC 8976: + * + * The ZONEMD RDATA wire format is encoded as follows: + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Serial | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scheme |Hash Algorithm | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | + * | Digest | + * / / + * / / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 2.2.1. The Serial Field + * + * The Serial field is a 32-bit unsigned integer in network byte order. + * It is the serial number from the zone's SOA record ([RFC1035], + * Section 3.3.13) for which the zone digest was generated. + * + * It is included here to clearly bind the ZONEMD RR to a particular + * version of the zone's content. Without the serial number, a stand- + * alone ZONEMD digest has no obvious association to any particular + * instance of a zone. + * + * 2.2.2. The Scheme Field + * + * The Scheme field is an 8-bit unsigned integer that identifies the + * methods by which data is collated and presented as input to the + * hashing function. + * + * Herein, SIMPLE, with Scheme value 1, is the only standardized Scheme + * defined for ZONEMD records and it MUST be supported by + * implementations. The "ZONEMD Schemes" registry is further described + * in Section 5. + * + * Scheme values 240-254 are allocated for Private Use. + * + * 2.2.3. The Hash Algorithm Field + * + * The Hash Algorithm field is an 8-bit unsigned integer that identifies + * the cryptographic hash algorithm used to construct the digest. + * + * Herein, SHA384 ([RFC6234]), with Hash Algorithm value 1, is the only + * standardized Hash Algorithm defined for ZONEMD records that MUST be + * supported by implementations. When SHA384 is used, the size of the + * Digest field is 48 octets. The result of the SHA384 digest algorithm + * MUST NOT be truncated, and the entire 48-octet digest is published in + * the ZONEMD record. + * + * SHA512 ([RFC6234]), with Hash Algorithm value 2, is also defined for + * ZONEMD records and SHOULD be supported by implementations. When + * SHA512 is used, the size of the Digest field is 64 octets. The + * result of the SHA512 digest algorithm MUST NOT be truncated, and the + * entire 64-octet digest is published in the ZONEMD record. + * + * Hash Algorithm values 240-254 are allocated for Private Use. + * + * The "ZONEMD Hash Algorithms" registry is further described in + * Section 5. + * + * 2.2.4. The Digest Field + * + * The Digest field is a variable-length sequence of octets containing + * the output of the hash algorithm. The length of the Digest field is + * determined by deducting the fixed size of the Serial, Scheme, and + * Hash Algorithm fields from the RDATA size in the ZONEMD RR header. + * + * The Digest field MUST NOT be shorter than 12 octets. Digests for the + * SHA384 and SHA512 hash algorithms specified herein are never + * truncated. Digests for future hash algorithms MAY be truncated but + * MUST NOT be truncated to a length that results in less than 96 bits + * (12 octets) of equivalent strength. + * + * Section 3 describes how to calculate the digest for a zone. + * Section 4 describes how to use the digest to verify the contents of a + * zone. + * + */ + +ISC_RUN_TEST_IMPL(zonemd) { + text_ok_t text_ok[] = { + TEXT_INVALID(""), + /* No digest scheme or digest type*/ + TEXT_INVALID("0"), + /* No digest type */ + TEXT_INVALID("0 0"), + /* No digest */ + TEXT_INVALID("0 0 0"), + /* No digest */ + TEXT_INVALID("99999999 0 0"), + /* No digest */ + TEXT_INVALID("2019020700 0 0"), + /* Digest too short */ + TEXT_INVALID("2019020700 1 1 DEADBEEF"), + /* Digest too short */ + TEXT_INVALID("2019020700 1 2 DEADBEEF"), + /* Digest too short */ + TEXT_INVALID("2019020700 1 3 DEADBEEFDEADBEEFDEADBE"), + /* Digest type unknown */ + TEXT_VALID("2019020700 1 3 DEADBEEFDEADBEEFDEADBEEF"), + /* Digest type max */ + TEXT_VALID("2019020700 1 255 DEADBEEFDEADBEEFDEADBEEF"), + /* Digest type too big */ + TEXT_INVALID("2019020700 0 256 DEADBEEFDEADBEEFDEADBEEF"), + /* Scheme max */ + TEXT_VALID("2019020700 255 3 DEADBEEFDEADBEEFDEADBEEF"), + /* Scheme too big */ + TEXT_INVALID("2019020700 256 3 DEADBEEFDEADBEEFDEADBEEF"), + /* SHA384 */ + TEXT_VALID("2019020700 1 1 " + "7162D2BB75C047A53DE98767C9192BEB" + "14DB01E7E2267135DAF0230A 19BA4A31" + "6AF6BF64AA5C7BAE24B2992850300509"), + /* SHA512 */ + TEXT_VALID("2019020700 1 2 " + "08CFA1115C7B948C4163A901270395EA" + "226A930CD2CBCF2FA9A5E6EB 85F37C8A" + "4E114D884E66F176EAB121CB02DB7D65" + "2E0CC4827E7A3204 F166B47E5613FD27"), + /* SHA384 too short and with private scheme */ + TEXT_INVALID("2021042801 0 1 " + "7162D2BB75C047A53DE98767C9192BEB" + "6AF6BF64AA5C7BAE24B2992850300509"), + /* SHA512 too short and with private scheme */ + TEXT_INVALID("2021042802 5 2 " + "A897B40072ECAE9E4CA3F1F227DE8F5E" + "480CDEBB16DFC64C1C349A7B5F6C71AB" + "E8A88B76EF0BA1604EC25752E946BF98"), + 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), + /* + * Short. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + /* + * Short 11-octet digest. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00), + /* + * Minimal, 12-octet hash for an undefined digest type. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00), + /* + * SHA-384 is defined, so we insist there be a digest of + * the expected length. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00), + /* + * 48-octet digest, valid for SHA-384. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, + 0xce), + /* + * 56-octet digest, too long for SHA-384. + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce), + /* + * 56-octet digest, too short for SHA-512 + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad), + /* + * 64-octet digest, just right for SHA-512 + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef), + /* + * 72-octet digest, too long for SHA-512 + */ + WIRE_INVALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, + 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce), + /* + * 56-octet digest, valid for an undefined digest type. + */ + WIRE_VALID(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, + 0xef, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce, + 0xde, 0xad, 0xbe, 0xef, 0xfa, 0xce), + /* + * Sentinel. + */ + WIRE_SENTINEL() + }; + + check_rdata(text_ok, wire_ok, NULL, false, dns_rdataclass_in, + dns_rdatatype_zonemd, sizeof(dns_rdata_zonemd_t)); +} + +ISC_RUN_TEST_IMPL(atcname) { + unsigned int i; + +#define UNR "# Unexpected result from dns_rdatatype_atcname for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_atcname((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_nsec: + case dns_rdatatype_key: + case dns_rdatatype_rrsig: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + } +#undef UNR +} + +ISC_RUN_TEST_IMPL(atparent) { + unsigned int i; + +#define UNR "# Unexpected result from dns_rdatatype_atparent for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_atparent((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_ds: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + } +#undef UNR +} + +ISC_RUN_TEST_IMPL(iszonecutauth) { + unsigned int i; +#define UNR "# Unexpected result from dns_rdatatype_iszonecutauth for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_iszonecutauth((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_ns: + case dns_rdatatype_ds: + case dns_rdatatype_nsec: + case dns_rdatatype_key: + case dns_rdatatype_rrsig: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + } +#undef UNR +} + +ISC_TEST_LIST_START + +/* types */ +ISC_TEST_ENTRY(amtrelay) +ISC_TEST_ENTRY(apl) +ISC_TEST_ENTRY(atma) +ISC_TEST_ENTRY(cdnskey) +ISC_TEST_ENTRY(csync) +ISC_TEST_ENTRY(dnskey) +ISC_TEST_ENTRY(doa) +ISC_TEST_ENTRY(ds) +ISC_TEST_ENTRY(eid) +ISC_TEST_ENTRY(hip) +ISC_TEST_ENTRY(https_svcb) +ISC_TEST_ENTRY(isdn) +ISC_TEST_ENTRY(key) +ISC_TEST_ENTRY(loc) +ISC_TEST_ENTRY(nimloc) +ISC_TEST_ENTRY(nsec) +ISC_TEST_ENTRY(nsec3) +ISC_TEST_ENTRY(nxt) +ISC_TEST_ENTRY(rkey) +ISC_TEST_ENTRY(sshfp) +ISC_TEST_ENTRY(wks) +ISC_TEST_ENTRY(zonemd) + +/* other tests */ +ISC_TEST_ENTRY(edns_client_subnet) +ISC_TEST_ENTRY(atcname) +ISC_TEST_ENTRY(atparent) +ISC_TEST_ENTRY(iszonecutauth) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rdataset_test.c b/tests/dns/rdataset_test.c new file mode 100644 index 0000000..fc21b29 --- /dev/null +++ b/tests/dns/rdataset_test.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/util.h> + +#include <dns/rdataset.h> +#include <dns/rdatastruct.h> + +#include <tests/dns.h> + +/* test trimming of rdataset TTLs */ +ISC_RUN_TEST_IMPL(trimttl) { + dns_rdataset_t rdataset, sigrdataset; + dns_rdata_rrsig_t rrsig; + isc_stdtime_t ttltimenow, ttltimeexpire; + + ttltimenow = 10000000; + ttltimeexpire = ttltimenow + 800; + + UNUSED(state); + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&sigrdataset); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimeexpire; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, true); + assert_int_equal(rdataset.ttl, 800); + assert_int_equal(sigrdataset.ttl, 800); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, true); + assert_int_equal(rdataset.ttl, 120); + assert_int_equal(sigrdataset.ttl, 120); + + rdataset.ttl = 900; + sigrdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + false); + assert_int_equal(rdataset.ttl, 0); + assert_int_equal(sigrdataset.ttl, 0); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimeexpire; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, true); + assert_int_equal(rdataset.ttl, 800); + assert_int_equal(sigrdataset.ttl, 800); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, true); + assert_int_equal(rdataset.ttl, 120); + assert_int_equal(sigrdataset.ttl, 120); + + sigrdataset.ttl = 900; + rdataset.ttl = 1000; + rrsig.timeexpire = ttltimenow - 200; + rrsig.originalttl = 1000; + + dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow, + false); + assert_int_equal(rdataset.ttl, 0); + assert_int_equal(sigrdataset.ttl, 0); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(trimttl) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rdatasetstats_test.c b/tests/dns/rdatasetstats_test.c new file mode 100644 index 0000000..7438034 --- /dev/null +++ b/tests/dns/rdatasetstats_test.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/print.h> +#include <isc/util.h> + +#include <dns/stats.h> + +#include <tests/dns.h> + +static void +set_typestats(dns_stats_t *stats, dns_rdatatype_t type) { + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = 0; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); + + attributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); +} + +static void +set_nxdomainstats(dns_stats_t *stats) { + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN; + which = DNS_RDATASTATSTYPE_VALUE(0, attributes); + dns_rdatasetstats_increment(stats, which); +} + +static void +mark_stale(dns_stats_t *stats, dns_rdatatype_t type, int from, int to) { + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = from; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_decrement(stats, which); + + attributes |= to; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); + + attributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET | from; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_decrement(stats, which); + + attributes |= to; + which = DNS_RDATASTATSTYPE_VALUE(type, attributes); + dns_rdatasetstats_increment(stats, which); +} + +static void +mark_nxdomain_stale(dns_stats_t *stats, int from, int to) { + dns_rdatastatstype_t which; + unsigned int attributes; + + attributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN | from; + which = DNS_RDATASTATSTYPE_VALUE(0, attributes); + dns_rdatasetstats_decrement(stats, which); + + attributes |= to; + which = DNS_RDATASTATSTYPE_VALUE(0, attributes); + dns_rdatasetstats_increment(stats, which); +} + +#define ATTRIBUTE_SET(y) ((attributes & (y)) != 0) +static void +verify_active_counters(dns_rdatastatstype_t which, uint64_t value, void *arg) { + unsigned int attributes; +#if debug + unsigned int type; +#endif /* if debug */ + + UNUSED(which); + UNUSED(arg); + + attributes = DNS_RDATASTATSTYPE_ATTR(which); +#if debug + type = DNS_RDATASTATSTYPE_BASE(which); + + fprintf(stderr, "%s%s%s%s%s/%u, %u\n", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) ? "O" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXRRSET) ? "!" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_ANCIENT) ? "~" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_STALE) ? "#" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) ? "X" : " ", + type, (unsigned)value); +#endif /* if debug */ + if ((attributes & DNS_RDATASTATSTYPE_ATTR_ANCIENT) == 0 && + (attributes & DNS_RDATASTATSTYPE_ATTR_STALE) == 0) + { + assert_int_equal(value, 1); + } else { + assert_int_equal(value, 0); + } +} + +static void +verify_stale_counters(dns_rdatastatstype_t which, uint64_t value, void *arg) { + unsigned int attributes; +#if debug + unsigned int type; +#endif /* if debug */ + + UNUSED(which); + UNUSED(arg); + + attributes = DNS_RDATASTATSTYPE_ATTR(which); +#if debug + type = DNS_RDATASTATSTYPE_BASE(which); + + fprintf(stderr, "%s%s%s%s%s/%u, %u\n", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) ? "O" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXRRSET) ? "!" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_ANCIENT) ? "~" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_STALE) ? "#" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) ? "X" : " ", + type, (unsigned)value); +#endif /* if debug */ + if ((attributes & DNS_RDATASTATSTYPE_ATTR_STALE) != 0) { + assert_int_equal(value, 1); + } else { + assert_int_equal(value, 0); + } +} + +static void +verify_ancient_counters(dns_rdatastatstype_t which, uint64_t value, void *arg) { + unsigned int attributes; +#if debug + unsigned int type; +#endif /* if debug */ + + UNUSED(which); + UNUSED(arg); + + attributes = DNS_RDATASTATSTYPE_ATTR(which); +#if debug + type = DNS_RDATASTATSTYPE_BASE(which); + + fprintf(stderr, "%s%s%s%s%s/%u, %u\n", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) ? "O" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXRRSET) ? "!" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_ANCIENT) ? "~" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_STALE) ? "#" : " ", + ATTRIBUTE_SET(DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) ? "X" : " ", + type, (unsigned)value); +#endif /* if debug */ + if ((attributes & DNS_RDATASTATSTYPE_ATTR_ANCIENT) != 0) { + assert_int_equal(value, 1); + } else { + assert_int_equal(value, 0); + } +} +/* + * Individual unit tests + */ + +/* + * Test that rdatasetstats counters are properly set when moving from + * active -> stale -> ancient. + */ +static void +rdatasetstats(void **state, bool servestale) { + unsigned int i; + unsigned int from = 0; + dns_stats_t *stats = NULL; + isc_result_t result; + + UNUSED(state); + + result = dns_rdatasetstats_create(mctx, &stats); + assert_int_equal(result, ISC_R_SUCCESS); + + /* First 255 types. */ + for (i = 1; i <= 255; i++) { + set_typestats(stats, (dns_rdatatype_t)i); + } + /* Specials */ + set_typestats(stats, (dns_rdatatype_t)1000); + set_nxdomainstats(stats); + + /* Check that all active counters are set to appropriately. */ + dns_rdatasetstats_dump(stats, verify_active_counters, NULL, 1); + + if (servestale) { + /* Mark stale */ + for (i = 1; i <= 255; i++) { + mark_stale(stats, (dns_rdatatype_t)i, 0, + DNS_RDATASTATSTYPE_ATTR_STALE); + } + mark_stale(stats, (dns_rdatatype_t)1000, 0, + DNS_RDATASTATSTYPE_ATTR_STALE); + mark_nxdomain_stale(stats, 0, DNS_RDATASTATSTYPE_ATTR_STALE); + + /* Check that all counters are set to appropriately. */ + dns_rdatasetstats_dump(stats, verify_stale_counters, NULL, 1); + + /* Set correct staleness state */ + from = DNS_RDATASTATSTYPE_ATTR_STALE; + } + + /* Mark ancient */ + for (i = 1; i <= 255; i++) { + mark_stale(stats, (dns_rdatatype_t)i, from, + DNS_RDATASTATSTYPE_ATTR_ANCIENT); + } + mark_stale(stats, (dns_rdatatype_t)1000, from, + DNS_RDATASTATSTYPE_ATTR_ANCIENT); + mark_nxdomain_stale(stats, from, DNS_RDATASTATSTYPE_ATTR_ANCIENT); + + /* + * Check that all counters are set to appropriately. + */ + dns_rdatasetstats_dump(stats, verify_ancient_counters, NULL, 1); + + dns_stats_detach(&stats); +} + +/* + * Test that rdatasetstats counters are properly set when moving from + * active -> stale -> ancient. + */ +ISC_RUN_TEST_IMPL(active_stale_ancient) { rdatasetstats(state, true); } + +/* + * Test that rdatasetstats counters are properly set when moving from + * active -> ancient. + */ +ISC_RUN_TEST_IMPL(active_ancient) { rdatasetstats(state, false); } + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(active_stale_ancient) +ISC_TEST_ENTRY(active_ancient) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/resolver_test.c b/tests/dns/resolver_test.c new file mode 100644 index 0000000..4967ffc --- /dev/null +++ b/tests/dns/resolver_test.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/app.h> +#include <isc/buffer.h> +#include <isc/net.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/dispatch.h> +#include <dns/name.h> +#include <dns/resolver.h> +#include <dns/view.h> + +#include <tests/dns.h> + +static dns_dispatchmgr_t *dispatchmgr = NULL; +static dns_dispatch_t *dispatch = NULL; +static dns_view_t *view = NULL; + +static int +_setup(void **state) { + isc_result_t result; + isc_sockaddr_t local; + + setup_managers(state); + + result = dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_makeview("view", true, &view); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_sockaddr_any(&local); + result = dns_dispatch_createudp(dispatchmgr, &local, &dispatch); + assert_int_equal(result, ISC_R_SUCCESS); + + return (0); +} + +static int +_teardown(void **state) { + dns_dispatch_detach(&dispatch); + dns_view_detach(&view); + dns_dispatchmgr_detach(&dispatchmgr); + + teardown_managers(state); + + return (0); +} + +static void +mkres(dns_resolver_t **resolverp) { + isc_result_t result; + + result = dns_resolver_create(view, taskmgr, 1, 1, netmgr, timermgr, 0, + dispatchmgr, dispatch, NULL, resolverp); + assert_int_equal(result, ISC_R_SUCCESS); +} + +static void +destroy_resolver(dns_resolver_t **resolverp) { + dns_resolver_shutdown(*resolverp); + dns_resolver_detach(resolverp); +} + +/* dns_resolver_create */ +ISC_RUN_TEST_IMPL(dns_resolver_create) { + dns_resolver_t *resolver = NULL; + + UNUSED(state); + + mkres(&resolver); + destroy_resolver(&resolver); +} + +/* dns_resolver_gettimeout */ +ISC_RUN_TEST_IMPL(dns_resolver_gettimeout) { + dns_resolver_t *resolver = NULL; + unsigned int timeout; + + UNUSED(state); + + mkres(&resolver); + + timeout = dns_resolver_gettimeout(resolver); + assert_true(timeout > 0); + + destroy_resolver(&resolver); +} + +/* dns_resolver_settimeout */ +ISC_RUN_TEST_IMPL(dns_resolver_settimeout) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(state); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, default_timeout + 1); + timeout = dns_resolver_gettimeout(resolver); + assert_true(timeout == default_timeout + 1); + + destroy_resolver(&resolver); +} + +/* dns_resolver_settimeout */ +ISC_RUN_TEST_IMPL(dns_resolver_settimeout_default) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(state); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, default_timeout + 100); + + timeout = dns_resolver_gettimeout(resolver); + assert_int_equal(timeout, default_timeout + 100); + + dns_resolver_settimeout(resolver, 0); + timeout = dns_resolver_gettimeout(resolver); + assert_int_equal(timeout, default_timeout); + + destroy_resolver(&resolver); +} + +/* dns_resolver_settimeout below minimum */ +ISC_RUN_TEST_IMPL(dns_resolver_settimeout_belowmin) { + dns_resolver_t *resolver = NULL; + unsigned int default_timeout, timeout; + + UNUSED(state); + + mkres(&resolver); + + default_timeout = dns_resolver_gettimeout(resolver); + dns_resolver_settimeout(resolver, 9000); + + timeout = dns_resolver_gettimeout(resolver); + assert_int_equal(timeout, default_timeout); + + destroy_resolver(&resolver); +} + +/* dns_resolver_settimeout over maximum */ +ISC_RUN_TEST_IMPL(dns_resolver_settimeout_overmax) { + dns_resolver_t *resolver = NULL; + unsigned int timeout; + + UNUSED(state); + + mkres(&resolver); + + dns_resolver_settimeout(resolver, 4000000); + timeout = dns_resolver_gettimeout(resolver); + assert_in_range(timeout, 0, 3999999); + destroy_resolver(&resolver); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_resolver_create, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_resolver_gettimeout, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_resolver_settimeout, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_resolver_settimeout_default, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_resolver_settimeout_belowmin, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_resolver_settimeout_overmax, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/rsa_test.c b/tests/dns/rsa_test.c new file mode 100644 index 0000000..d5b7a7f --- /dev/null +++ b/tests/dns/rsa_test.c @@ -0,0 +1,233 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/print.h> +#include <isc/util.h> + +#include "dst_internal.h" + +#include <tests/dns.h> + +static int +setup_test(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dst_lib_init(mctx, NULL); + + if (result != ISC_R_SUCCESS) { + return (1); + } + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +static unsigned char d[10] = { 0xa, 0x10, 0xbb, 0, 0xfe, + 0x15, 0x1, 0x88, 0xcc, 0x7d }; + +static unsigned char sigsha1[256] = { + 0x45, 0x55, 0xd6, 0xf8, 0x05, 0xd2, 0x2e, 0x79, 0x14, 0x2b, 0x1b, 0xd1, + 0x4b, 0xb7, 0xcd, 0xc0, 0xa2, 0xf3, 0x85, 0x32, 0x1f, 0xa3, 0xfd, 0x1f, + 0x30, 0xe0, 0xde, 0xb2, 0x6f, 0x3c, 0x8e, 0x2b, 0x82, 0x92, 0xcd, 0x1c, + 0x1b, 0xdf, 0xe6, 0xd5, 0x4d, 0x93, 0xe6, 0xaa, 0x40, 0x28, 0x1b, 0x7b, + 0x2e, 0x40, 0x4d, 0xb5, 0x4d, 0x43, 0xe8, 0xfc, 0x93, 0x86, 0x68, 0xe3, + 0xbf, 0x73, 0x9a, 0x1e, 0x6b, 0x5d, 0x52, 0xb8, 0x98, 0x1c, 0x94, 0xe1, + 0x85, 0x8b, 0xee, 0xb1, 0x4f, 0x22, 0x71, 0xcb, 0xfd, 0xb2, 0xa8, 0x88, + 0x64, 0xb4, 0xb1, 0x4a, 0xa1, 0x7a, 0xce, 0x52, 0x83, 0xd8, 0xf2, 0x9e, + 0x67, 0x4c, 0xc3, 0x37, 0x74, 0xfe, 0xe0, 0x25, 0x2a, 0xfd, 0xa3, 0x09, + 0xff, 0x8a, 0x92, 0x0d, 0xa9, 0xb3, 0x90, 0x23, 0xbe, 0x6a, 0x2c, 0x9e, + 0x5c, 0x6d, 0xb4, 0xa7, 0xd7, 0x97, 0xdd, 0xc6, 0xb8, 0xae, 0xd4, 0x88, + 0x64, 0x63, 0x1e, 0x85, 0x20, 0x09, 0xea, 0xc4, 0x0b, 0xca, 0xbf, 0x83, + 0x5c, 0x89, 0xae, 0x64, 0x15, 0x76, 0x06, 0x51, 0xb6, 0xa1, 0x99, 0xb2, + 0x3c, 0x50, 0x99, 0x86, 0x7d, 0xc7, 0xca, 0x4e, 0x1d, 0x2c, 0x17, 0xbb, + 0x6c, 0x7a, 0xc9, 0x3f, 0x5e, 0x28, 0x57, 0x2c, 0xda, 0x01, 0x1d, 0xe8, + 0x01, 0xf8, 0xf6, 0x37, 0xe1, 0x34, 0x56, 0xae, 0x6e, 0xb1, 0xd4, 0xa2, + 0xc4, 0x02, 0xc1, 0xca, 0x96, 0xb0, 0x06, 0x72, 0x2a, 0x27, 0xaa, 0xc8, + 0xd5, 0x50, 0x81, 0x49, 0x46, 0x33, 0xf8, 0xf7, 0x6b, 0xf4, 0x9c, 0x30, + 0x90, 0x50, 0xf6, 0x16, 0x76, 0x9d, 0xc6, 0x73, 0xb5, 0xbc, 0x8a, 0xb6, + 0x1d, 0x98, 0xcb, 0xce, 0x36, 0x6f, 0x60, 0xec, 0x96, 0x49, 0x08, 0x85, + 0x5b, 0xc1, 0x8e, 0xb0, 0xea, 0x9e, 0x1f, 0xd6, 0x27, 0x7f, 0xb6, 0xe0, + 0x04, 0x12, 0xd2, 0x81 +}; + +static unsigned char sigsha256[256] = { + 0x83, 0x53, 0x15, 0xfc, 0xca, 0xdb, 0xf6, 0x0d, 0x53, 0x24, 0x5b, 0x5a, + 0x8e, 0xd0, 0xbe, 0x5e, 0xbc, 0xe8, 0x9e, 0x92, 0x3c, 0xfa, 0x93, 0x03, + 0xce, 0x2f, 0xc7, 0x6d, 0xd0, 0xbb, 0x9d, 0x06, 0x83, 0xc6, 0xd3, 0xc0, + 0xc1, 0x57, 0x9c, 0x82, 0x17, 0x7f, 0xb5, 0xf8, 0x31, 0x18, 0xda, 0x46, + 0x05, 0x2c, 0xf8, 0xea, 0xaa, 0xcd, 0x99, 0x18, 0xff, 0x23, 0x5e, 0xef, + 0xf0, 0x87, 0x47, 0x6e, 0x91, 0xfd, 0x19, 0x0b, 0x39, 0x19, 0x6a, 0xc8, + 0xdf, 0x71, 0x66, 0x8e, 0xa9, 0xa0, 0x79, 0x5c, 0x2c, 0x52, 0x00, 0x61, + 0x17, 0x86, 0x66, 0x03, 0x52, 0xad, 0xec, 0x06, 0x53, 0xd9, 0x6d, 0xe3, + 0xe3, 0xea, 0x28, 0x15, 0xb3, 0x75, 0xf4, 0x61, 0x7d, 0xed, 0x69, 0x2c, + 0x24, 0xf3, 0x21, 0xb1, 0x8a, 0xea, 0x60, 0xa2, 0x9e, 0x6a, 0xa6, 0x53, + 0x12, 0xf6, 0x5c, 0xef, 0xd7, 0x49, 0x4a, 0x02, 0xe7, 0xf8, 0x64, 0x89, + 0x13, 0xac, 0xd5, 0x1e, 0x58, 0xff, 0xa1, 0x63, 0xdd, 0xa0, 0x1f, 0x44, + 0x99, 0x6a, 0x59, 0x7f, 0x35, 0xbd, 0xf1, 0xf3, 0x7a, 0x28, 0x44, 0xe3, + 0x4c, 0x68, 0xb1, 0xb3, 0x97, 0x3c, 0x46, 0xe3, 0xc2, 0x12, 0x9e, 0x68, + 0x0b, 0xa6, 0x6c, 0x8f, 0x58, 0x48, 0x44, 0xa4, 0xf7, 0xa7, 0xc2, 0x91, + 0x8f, 0xbf, 0x00, 0xd0, 0x01, 0x35, 0xd4, 0x86, 0x6e, 0x1f, 0xea, 0x42, + 0x60, 0xb1, 0x84, 0x27, 0xf4, 0x99, 0x36, 0x06, 0x98, 0x12, 0x83, 0x32, + 0x9f, 0xcd, 0x50, 0x5a, 0x5e, 0xb8, 0x8e, 0xfe, 0x8d, 0x8d, 0x33, 0x2d, + 0x45, 0xe1, 0xc9, 0xdf, 0x2a, 0xd8, 0x38, 0x1d, 0x95, 0xd4, 0x42, 0xee, + 0x93, 0x5b, 0x0f, 0x1e, 0x07, 0x06, 0x3a, 0x92, 0xf1, 0x59, 0x1d, 0x6e, + 0x1c, 0x31, 0xf3, 0xce, 0xa9, 0x1f, 0xad, 0x4d, 0x76, 0x4d, 0x24, 0x98, + 0xe2, 0x0e, 0x8c, 0x35 +}; + +static unsigned char sigsha512[512] = { + 0x4e, 0x2f, 0x63, 0x42, 0xc5, 0xf3, 0x05, 0x4a, 0xa6, 0x3a, 0x93, 0xa0, + 0xd9, 0x33, 0xa0, 0xd1, 0x46, 0x33, 0x42, 0xe8, 0x74, 0xeb, 0x3b, 0x10, + 0x82, 0xd7, 0xcf, 0x39, 0x23, 0xb3, 0xe9, 0x23, 0x53, 0x87, 0x8c, 0xee, + 0x78, 0xcb, 0xb3, 0xd9, 0xd2, 0x6d, 0x1a, 0x7c, 0x01, 0x4f, 0xed, 0x8d, + 0xf2, 0x72, 0xe4, 0x6a, 0x00, 0x8a, 0x60, 0xa6, 0xd5, 0x9c, 0x43, 0x6c, + 0xef, 0x38, 0x0c, 0x74, 0x82, 0x5d, 0x22, 0xaa, 0x87, 0x81, 0x90, 0x9c, + 0x64, 0x07, 0x9b, 0x13, 0x51, 0xe0, 0xa5, 0xc2, 0x83, 0x78, 0x2b, 0x9b, + 0xb3, 0x8a, 0x9d, 0x36, 0x33, 0xbd, 0x0d, 0x53, 0x84, 0xae, 0xe8, 0x13, + 0x36, 0xf6, 0xdf, 0x96, 0xe9, 0xda, 0xc3, 0xd7, 0xa9, 0x2f, 0xf3, 0x5e, + 0x5f, 0x1f, 0x7f, 0x38, 0x7e, 0x8d, 0xbe, 0x90, 0x5e, 0x13, 0xb2, 0x20, + 0xbb, 0x9d, 0xfe, 0xe1, 0x52, 0xce, 0xe6, 0x80, 0xa7, 0x95, 0x24, 0x59, + 0xe3, 0xac, 0x24, 0xc4, 0xfa, 0x1c, 0x44, 0x34, 0x29, 0x8d, 0xb1, 0xd0, + 0xd9, 0x4c, 0xff, 0xc4, 0xdb, 0xca, 0xc4, 0x3f, 0x38, 0xf9, 0xe4, 0xaf, + 0x75, 0x0a, 0x67, 0x4d, 0xa0, 0x2b, 0xb0, 0x83, 0xce, 0x53, 0xc4, 0xb9, + 0x2e, 0x61, 0xb6, 0x64, 0xe5, 0xb5, 0xe5, 0xac, 0x9d, 0x51, 0xec, 0x58, + 0x42, 0x90, 0x78, 0xf6, 0x46, 0x96, 0xef, 0xb6, 0x97, 0xb7, 0x54, 0x28, + 0x1a, 0x4c, 0x29, 0xf4, 0x7a, 0x33, 0xc6, 0x07, 0xfd, 0xec, 0x97, 0x36, + 0x1d, 0x42, 0x88, 0x94, 0x27, 0xc2, 0xa3, 0xe1, 0xd4, 0x87, 0xa1, 0x8a, + 0x2b, 0xff, 0x47, 0x60, 0xfe, 0x1f, 0xaf, 0xc2, 0xeb, 0x17, 0xdd, 0x56, + 0xc5, 0x94, 0x5c, 0xcb, 0x23, 0xe5, 0x49, 0x4d, 0x99, 0x06, 0x02, 0x5a, + 0xfc, 0xfc, 0xdc, 0xee, 0x49, 0xbc, 0x47, 0x60, 0xff, 0x6a, 0x63, 0x8b, + 0xe1, 0x2e, 0xa3, 0xa7 +}; + +/* RSA verify */ +ISC_RUN_TEST_IMPL(isc_rsa_verify) { + isc_result_t ret; + dns_fixedname_t fname; + isc_buffer_t buf; + dns_name_t *name; + dst_key_t *key = NULL; + dst_context_t *ctx = NULL; + isc_region_t r; + + UNUSED(state); + + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&buf, "rsa.", 4); + isc_buffer_add(&buf, 4); + ret = dns_name_fromtext(name, &buf, NULL, 0, NULL); + assert_int_equal(ret, ISC_R_SUCCESS); + + ret = dst_key_fromfile(name, 29238, DST_ALG_RSASHA256, DST_TYPE_PUBLIC, + TESTS_DIR, mctx, &key); + assert_int_equal(ret, ISC_R_SUCCESS); + + /* RSASHA1 - May not be supported by the OS */ + if (dst_algorithm_supported(DST_ALG_RSASHA1)) { + key->key_alg = DST_ALG_RSASHA1; + + ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, 0, &ctx); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = sigsha1; + r.length = 256; + ret = dst_context_verify(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + } + + /* RSASHA256 */ + + key->key_alg = DST_ALG_RSASHA256; + + ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 0, + &ctx); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = sigsha256; + r.length = 256; + ret = dst_context_verify(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + + /* RSASHA512 */ + + key->key_alg = DST_ALG_RSASHA512; + + ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 0, + &ctx); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = d; + r.length = 10; + ret = dst_context_adddata(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + r.base = sigsha512; + r.length = 256; + ret = dst_context_verify(ctx, &r); + assert_int_equal(ret, ISC_R_SUCCESS); + + dst_context_destroy(&ctx); + + dst_key_free(&key); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(isc_rsa_verify, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/sigs_test.c b/tests/dns/sigs_test.c new file mode 100644 index 0000000..881c900 --- /dev/null +++ b/tests/dns/sigs_test.c @@ -0,0 +1,446 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/list.h> +#include <isc/region.h> +#include <isc/result.h> +#include <isc/stdtime.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/diff.h> +#include <dns/dnssec.h> +#include <dns/fixedname.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdatastruct.h> +#include <dns/rdatatype.h> +#include <dns/types.h> +#include <dns/zone.h> + +#include <dst/dst.h> + +#include "zone_p.h" + +#include <tests/dns.h> + +/*% + * Structure characterizing a single diff tuple in the dns_diff_t structure + * prepared by dns__zone_updatesigs(). + */ +typedef struct { + dns_diffop_t op; + const char *owner; + dns_ttl_t ttl; + const char *type; +} zonediff_t; + +#define ZONEDIFF_SENTINEL \ + { \ + 0, NULL, 0, NULL \ + } + +/*% + * Structure defining a dns__zone_updatesigs() test. + */ +typedef struct { + const char *description; /* test description */ + const zonechange_t *changes; /* array of "raw" zone changes */ + const zonediff_t *zonediff; /* array of "processed" zone changes + * */ +} updatesigs_test_params_t; + +static int +setup_test(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dst_lib_init(mctx, NULL); + + if (result != ISC_R_SUCCESS) { + return (1); + } + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +/*% + * Check whether the 'found' tuple matches the 'expected' tuple. 'found' is + * the 'index'th tuple output by dns__zone_updatesigs() in test 'test'. + */ +static void +compare_tuples(const zonediff_t *expected, dns_difftuple_t *found, + size_t index) { + char found_covers[DNS_RDATATYPE_FORMATSIZE] = {}; + char found_type[DNS_RDATATYPE_FORMATSIZE] = {}; + char found_name[DNS_NAME_FORMATSIZE]; + isc_consttextregion_t typeregion; + dns_fixedname_t expected_fname; + dns_rdatatype_t expected_type; + dns_name_t *expected_name; + dns_rdata_rrsig_t rrsig; + isc_buffer_t typebuf; + isc_result_t result; + + REQUIRE(expected != NULL); + REQUIRE(found != NULL); + REQUIRE(index > 0); + + /* + * Check operation. + */ + assert_int_equal(expected->op, found->op); + + /* + * Check owner name. + */ + expected_name = dns_fixedname_initname(&expected_fname); + result = dns_name_fromstring(expected_name, expected->owner, 0, mctx); + assert_int_equal(result, ISC_R_SUCCESS); + dns_name_format(&found->name, found_name, sizeof(found_name)); + assert_true(dns_name_equal(expected_name, &found->name)); + + /* + * Check TTL. + */ + assert_int_equal(expected->ttl, found->ttl); + + /* + * Parse expected RR type. + */ + typeregion.base = expected->type; + typeregion.length = strlen(expected->type); + result = dns_rdatatype_fromtext(&expected_type, + (isc_textregion_t *)&typeregion); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Format found RR type for reporting purposes. + */ + isc_buffer_init(&typebuf, found_type, sizeof(found_type)); + result = dns_rdatatype_totext(found->rdata.type, &typebuf); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Check RR type. + */ + switch (expected->op) { + case DNS_DIFFOP_ADDRESIGN: + case DNS_DIFFOP_DELRESIGN: + /* + * Found tuple must be of type RRSIG. + */ + assert_int_equal(found->rdata.type, dns_rdatatype_rrsig); + if (found->rdata.type != dns_rdatatype_rrsig) { + break; + } + /* + * The signature must cover an RRset of type 'expected->type'. + */ + result = dns_rdata_tostruct(&found->rdata, &rrsig, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&typebuf, found_covers, sizeof(found_covers)); + result = dns_rdatatype_totext(rrsig.covered, &typebuf); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(expected_type, rrsig.covered); + break; + default: + /* + * Found tuple must be of type 'expected->type'. + */ + assert_int_equal(expected_type, found->rdata.type); + break; + } +} + +/*% + * Perform a single dns__zone_updatesigs() test defined in 'test'. All other + * arguments are expected to remain constant between subsequent invocations of + * this function. + */ +static void +updatesigs_test(const updatesigs_test_params_t *test, dns_zone_t *zone, + dns_db_t *db, dst_key_t *zone_keys[], unsigned int nkeys, + isc_stdtime_t now) { + size_t tuples_expected, tuples_found, index; + dns_dbversion_t *version = NULL; + dns_diff_t raw_diff, zone_diff; + const zonediff_t *expected; + dns_difftuple_t *found; + isc_result_t result; + + dns__zonediff_t zonediff = { + .diff = &zone_diff, + .offline = false, + }; + + REQUIRE(test != NULL); + REQUIRE(test->description != NULL); + REQUIRE(test->changes != NULL); + REQUIRE(zone != NULL); + REQUIRE(db != NULL); + REQUIRE(zone_keys != NULL); + + /* + * Create a new version of the zone's database. + */ + result = dns_db_newversion(db, &version); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Create a diff representing the supplied changes. + */ + result = dns_test_difffromchanges(&raw_diff, test->changes, false); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Apply the "raw" diff to the new version of the zone's database as + * this is what dns__zone_updatesigs() expects to happen before it is + * called. + */ + dns_diff_apply(&raw_diff, db, version); + + /* + * Initialize the structure dns__zone_updatesigs() will modify. + */ + dns_diff_init(mctx, &zone_diff); + + /* + * Check whether dns__zone_updatesigs() behaves as expected. + */ + result = dns__zone_updatesigs(&raw_diff, db, version, zone_keys, nkeys, + zone, now - 3600, now + 3600, 0, now, + true, false, &zonediff); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_LIST_EMPTY(raw_diff.tuples)); + assert_false(ISC_LIST_EMPTY(zone_diff.tuples)); + + /* + * Ensure that the number of tuples in the zone diff is as expected. + */ + + tuples_expected = 0; + for (expected = test->zonediff; expected->owner != NULL; expected++) { + tuples_expected++; + } + + tuples_found = 0; + for (found = ISC_LIST_HEAD(zone_diff.tuples); found != NULL; + found = ISC_LIST_NEXT(found, link)) + { + tuples_found++; + } + + assert_int_equal(tuples_expected, tuples_found); + + /* + * Ensure that every tuple in the zone diff matches expectations. + */ + expected = test->zonediff; + index = 1; + for (found = ISC_LIST_HEAD(zone_diff.tuples); found != NULL; + found = ISC_LIST_NEXT(found, link)) + { + compare_tuples(expected, found, index); + expected++; + index++; + } + + /* + * Apply changes to zone database contents and clean up. + */ + dns_db_closeversion(db, &version, true); + dns_diff_clear(&zone_diff); + dns_diff_clear(&raw_diff); +} + +/* dns__zone_updatesigs() tests */ +ISC_RUN_TEST_IMPL(updatesigs_next) { + dst_key_t *zone_keys[DNS_MAXZONEKEYS]; + dns_zone_t *zone = NULL; + dns_db_t *db = NULL; + isc_result_t result; + unsigned int nkeys; + isc_stdtime_t now; + size_t i; + + UNUSED(state); + + /* + * Prepare a zone along with its signing keys. + */ + + result = dns_test_makezone("example", &zone, NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_loaddb(&db, dns_dbtype_zone, "example", + "testdata/master/master18.data"); + assert_int_equal(result, DNS_R_SEENINCLUDE); + + result = dns_zone_setkeydirectory(zone, TESTS_DIR "/testkeys"); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_stdtime_get(&now); + result = dns__zone_findkeys(zone, db, NULL, now, mctx, DNS_MAXZONEKEYS, + zone_keys, &nkeys); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(nkeys, 2); + + /* + * Define the tests to be run. Note that changes to zone database + * contents introduced by each test are preserved between tests. + */ + + const zonechange_t changes_add[] = { + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "bar" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_add[] = { + { DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_add = { + .description = "add new RRsets", + .changes = changes_add, + .zonediff = zonediff_add, + }; + + const zonechange_t changes_append[] = { + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo1" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo2" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_append[] = { + { DNS_DIFFOP_DELRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + { DNS_DIFFOP_ADD, "foo.example", 300, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_append = { + .description = "append multiple RRs to an existing RRset", + .changes = changes_append, + .zonediff = zonediff_append, + }; + + const zonechange_t changes_replace[] = { + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "bar" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "rab" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_replace[] = { + { DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_ADD, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_replace = { + .description = "replace an existing RRset", + .changes = changes_replace, + .zonediff = zonediff_replace, + }; + + const zonechange_t changes_delete[] = { + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "rab" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_delete[] = { + { DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" }, + { DNS_DIFFOP_DEL, "bar.example", 600, "TXT" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_delete = { + .description = "delete an existing RRset", + .changes = changes_delete, + .zonediff = zonediff_delete, + }; + + const zonechange_t changes_mixed[] = { + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz1" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "A", "127.0.0.1" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz2" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "AAAA", "::1" }, + ZONECHANGE_SENTINEL, + }; + const zonediff_t zonediff_mixed[] = { + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "TXT" }, + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "A" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "A" }, + { DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "AAAA" }, + { DNS_DIFFOP_ADD, "baz.example", 900, "AAAA" }, + ZONEDIFF_SENTINEL, + }; + const updatesigs_test_params_t test_mixed = { + .description = "add different RRsets with common owner name", + .changes = changes_mixed, + .zonediff = zonediff_mixed, + }; + + const updatesigs_test_params_t *tests[] = { + &test_add, &test_append, &test_replace, + &test_delete, &test_mixed, + }; + + /* + * Run tests. + */ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + updatesigs_test(tests[i], zone, db, zone_keys, nkeys, now); + } + + /* + * Clean up. + */ + for (i = 0; i < nkeys; i++) { + dst_key_free(&zone_keys[i]); + } + dns_db_detach(&db); + dns_zone_detach(&zone); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(updatesigs_next, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/testdata/db/data.db b/tests/dns/testdata/db/data.db new file mode 100644 index 0000000..67a4fba --- /dev/null +++ b/tests/dns/testdata/db/data.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns ns.vix.com. +a in ns ns2.vix.com. +a in ns ns3.vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/dbiterator/zone1.data b/tests/dns/testdata/dbiterator/zone1.data new file mode 100644 index 0000000..c380d39 --- /dev/null +++ b/tests/dns/testdata/dbiterator/zone1.data @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ in soa localhost. postmaster.localhost. ( + 2011080901 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 600 ) ;minimum + in ns ns + in ns ns2 +ns in a 10.0.0.1 +ns2 in a 10.0.0.2 + +a in txt "test" +b in txt "test" +c in txt "test" +d.e.f in txt "test" +e in txt "test" +f.g.h in txt "test" +f.g.i in txt "test" +f.g.j in txt "test" +k in txt "test" diff --git a/tests/dns/testdata/dbiterator/zone2.data b/tests/dns/testdata/dbiterator/zone2.data new file mode 100644 index 0000000..7265c27 --- /dev/null +++ b/tests/dns/testdata/dbiterator/zone2.data @@ -0,0 +1,319 @@ +; File written on Mon Aug 15 16:51:56 2011 +; dnssec_signzone version 9.7.3rc1 +test. 600 IN SOA localhost. postmaster.localhost. ( + 2011080901 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 minutes) + 604800 ; expire (1 week) + 600 ; minimum (10 minutes) + ) + 600 RRSIG SOA 7 1 600 20110914225156 ( + 20110815225156 39833 test. + IoQPcpx+Y2btVBBdM2H/9ppRMjphB1thwrdh + midhKH+MXDAauUIENucugi3zLsc1o2ke8LnQ + v3lCLd/bb5MD1otuS8vOw1GWEFhXOUBZU6wS + QwEIcG4BiSlz7/GvOlRa2znkOmZ3c8bD/J3Y + XUWDI3BEDPgrZqfxEvoMyPEWjO8= ) + 600 NS ns.test. + 600 NS ns2.test. + 600 RRSIG NS 7 1 600 20110914225156 ( + 20110815225156 39833 test. + OgEimhmFIAqlH0hyQy3pTsveBHKyqs9WfO1S + uDPRj3DFgFEAjoY473T8GxG2C+jTVL/UMVcb + BTZ8wIAiUHhqKLcmr0q/1X+kNUs7tNi+6oMn + /jxaOuRL6c8Kf2gl2t4g6JTwQqLQhUHTfQP+ + bEfKUr75VsVfxCQZIHlZ3/AlxZM= ) + 600 DNSKEY 256 3 7 ( + AwEAAc0FzrE7jUiaKIGZpIaFE8E989topAJN + dWIQUQ7BSKabmpBP2M+SXHwIiQ/yC25iqudO + IxjRcK7nHB1VoP84xU2oMj6eeSqQHf/bYaji + Y8IfR7lgrzoDWzq+0rtnKMJc/JM8SMkcoBAS + llvxarDJTZheZjlrCvhpRJC+FAkBsx81 + ) ; key id = 39833 + 600 DNSKEY 257 3 7 ( + AwEAAc55LPDhBLqfDUpjYYbBt+N63CiZtKrD + UDGeFAerbw0MWIUi3PgMr7yGVrj8e5Qjp9UN + zBUax6NdhlYVtFA8CwMTXGBjxgyqUoWpce08 + lswxfE70BpgUA6w5efs0/mYtX9/A76etCaSI + oNH2vfa47BCdCPDfC1uTgyeuNuDvhszHaSiD + 8OY7tLa/voecUlq38sdqi2raf2DvgOm7rdFa + reXOS/WIj7zd4XYrV1JGthxOMVlQ7zdv9rVd + UNUIF2d4hwCZJQr0ejhmvB3m/DuNmNOPYmnv + KTmLSE+IJ6baqYvKOVxwV+SaCnuJEjv+3Yrx + 8WQYD/iS9WBhC9FUit0dy+0= + ) ; key id = 57183 + 600 RRSIG DNSKEY 7 1 600 20110914225156 ( + 20110815225156 39833 test. + xPV+bSGUlbxA5MKBeeRbwUDh3Qc+dm77+OHQ + BHIr1L8/kRP5o5J7MqPA37kea6nhyltYf9xM + RsxyiaBGUUeLyWg/q6hTtkNgAHifOPAhiDz8 + AJDSTdSsq9RVtjdobAD0jyzz9sWnB+TPSOmj + Nlyd7VtPVEuSYljgawwfBBO3Kho= ) + 600 RRSIG DNSKEY 7 1 600 20110914225156 ( + 20110815225156 57183 test. + S3jkC7AvyFc4ShfHt6AWgS4zpx9DzWHBK9gV + 2H23OJzy8H1At/CjKxWVHLJ/io+ygryVnt/I + 47Jyhh9i43TnXj8il475YsweGnXGZSorrcXA + 3IsD2lOuRYnp3yetxe2ZrMGNDqqImE6X4x1a + UJI0cbE2UMZfUt8Rm5USiGzwAEgFD1OXxvMD + UT3flyp+Ote9FConK8gewV4wlJuBFemWT7BZ + lUYnoqfuAeEn2+1pIBS0iA0LNFjNBaEgtcjo + QeweN32yKoApau47Dl/Klw7KFT8+PLZ0QPbt + XAkJU7q94Q5aucDuHCSCTCc+2vZxdEnXKvRY + rfLuG8r/V5Kn+1iYrQ== ) + 0 NSEC3PARAM 1 0 10 - + 0 RRSIG NSEC3PARAM 7 1 0 20110914225156 ( + 20110815225156 39833 test. + kghSSeP8AZiQ/zmxgxAyG0itoUMo5adG5pxD + p8T3ZmbxEUSyG5acxBFkmeY39wVU0Cda8tWc + HHrMbB5e2GN8z6xJ0A4rVyXfKSYJSz+iKWfk + 7sOFRjd8OLYE3di6PwIpk6ORUiRPMFLDQCH0 + Q27hLsSoKyd50orKKI+ncjz7WzU= ) +a.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + UEVOlnL6CDRNCfk/Xge2oaGYCV1+ewwi5zJ0 + CX4DdwiNEkItL4HgBe8xXfxgFC3qySdsSYPE + 1krdFyIkAclMCwHECd1UwZbGlMTEUGrE1KOB + 8vQY+OhIV9TAhqNwnjbu7s2ZdNUv3wiUPcfk + hCJ4rzP6yeV2inLwZulXnhxb6Pk= ) +b.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + HcyQlO9io6Rc5e4vVqlRmK5PacOaFQJmdERG + 5Aobpgm1FuCLC7F+IMZ0d1XvBWnsw9iDzV43 + UKzTGqUSmDiSBzs4QzHlacGickIW8EOV4xyJ + +mcJ0FZh4YNbkt6CiX+8SF6IxfCMhRMjpSsK + rWqJMG3LXkI6W9stShzsYAFBOzQ= ) +e.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + jUn5FGRTL9OcFU7tvfkUnSwY8jA+8JynE0hi + ZJbYXDU5CiWGmR2B3yPHxUCewRqouyVCV8bc + xZsSuBxvcdYKryYDbjsmB83GlSEuxE9J7XZs + 8SxUP8PobLVqzXgEZS/XRU2G+R915ZDP9/iL + z9oYwc9TkeyXbp8J/ZsH88tG980= ) +c.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + cRxAj45oFDDCd8xQXxD1F0Qq8XeBWAj8EYS3 + 7nFXAgAy8sTczFvYCNGj79o7BALJwM4vc/wx + 6rjsiO/sHgfTMEBDq6lH9Wql72uhwavI2SrL + /h/wBP5q4BXlQ4xp6cLhhdifOWhNTvLP+Fe5 + U6yjvqneiKspze9SiFbcmRDiJds= ) +d.e.f.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + ENjCzr/P9rJmj5OJLzYwWtHtBg2Uz+qJDucz + I97Pq9F819/c5sxNfT4hgICCw6ZfT4ffbzye + fFJ0JVrh2cYOzu68ozlgek/Uml1UW0pDQVdI + s4zEgp4XK9wXUxtWChSqp5YXMdeHegZFu32i + IMNTbJDudwYSwhr2FyG92ZRi8Y8= ) +f.g.h.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + HT7iocFsfDjeX6j9RJdE3xfVGkIxhajFHgM/ + T/mJj/al4HKV6Ajia8DhpdfDrgM2m7r+Pgcn + FSIstfebQsuFCnHX/gIalDND/grHKsetQnMP + Y7O4QLsRnTV53fdlqQ4eT+jBW6fzJdGySVN+ + bg6kNJZS8DebjmlKtZz7tXjkP+4= ) +f.g.i.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + kHJJeNSL1rz4QRYqOzhGMQl1yIdio7l8Lg8H + f0TsvFLa6BudVtwKUm+Kz2QiDn7/Lew8w0KX + vVHxX/Vwl3Ixk54YgMKLNogz2TEvnh/VGiS7 + 8r0oSUrg0CFd+xDfxnLeRqX5NNfMuSJap5WH + Aw7IVeRjXDwJFYnytMEnTrhHHHg= ) +f.g.j.test. 600 IN TXT "test" + 600 RRSIG TXT 7 4 600 20110914225156 ( + 20110815225156 39833 test. + lIEHEhDFhOWK8W/F2xWELU2p/X77S2KTivm9 + sY4k3RPsLNHE7p+lF8p72Lcb79rtltnoVYtE + pTIiaUcmgGwfaI4cwfXbeuEgnuTiLg7Xrefx + 3GT86Q+8gfgbMXUmRA/eouWZhCOaYJN99gYz + urzDMiRLYmILHmLlnvo82SgXeuk= ) +k.test. 600 IN TXT "test" + 600 RRSIG TXT 7 2 600 20110914225156 ( + 20110815225156 39833 test. + wC3zgYWsuLga8Vu3QFu/Ci8SzRbA5bvjSmDj + NzcpjU5cvJBxtgzatCr02AaUC94bI0JzNrEB + nFyWCYw55lyy+bAHU1u05UcQmz0n5yxkvmHX + i8ZjMyQkAvNKodJHaFQqUKKIDuSHD2EziKqg + eNn55YRS11ihkODehUVNl7TnYeA= ) +ns.test. 600 IN A 10.0.0.1 + 600 RRSIG A 7 2 600 20110914225156 ( + 20110815225156 39833 test. + VyK/WlQ6ikXdjF/arGzyAyYhOc8IYNBp4QLW + gtYjvbjIcV5+9JINWmUs61VjJ14nES1sI0xb + 9vQJuiPXTM1awUAnvOKLhaX6fbJaEiR1w6Cf + RT5QKBMxNBKVStqdabHcigY4DUuc1PQk1vCw + yMUJt3nHNVMZk+XAycNHzBeYjik= ) +ns2.test. 600 IN A 10.0.0.2 + 600 RRSIG A 7 2 600 20110914225156 ( + 20110815225156 39833 test. + CX6UlZL+5NQJViKfbe/E3uIJk/wjUzoiHBhY + B6gS8nxZzlRPdTTXyMZoRa4etTZEbrRjnyXk + 1rP47faCUwbh//XqukN9f7FZ4Y39NpPS2XpX + 0Lx6M93Jz46lbzmseMFs2YmNMzzhN4uhRvl/ + 8gPtYsn9KMXnAlFfa4XrE5LNVyY= ) +1F3JQ6EANHNHOCMUPQTVNM339VDTR51C.test. 600 IN NSEC3 1 0 10 - 7QKPELF33JOK9BVJ7CKE99AHG40B0SH7 A RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + w7aS12lxLNh+G1B/2kEq1BO6IzYvyC8n/MGV + 0jvFnapNXGZMPrPxGeO2wkw1JXepuXCv98be + M4SjQywaH+VP6ZMTIfjxRxtcCM+aLAFhiz0l + /MILEkjemmxjAfvV7emRVMwCGcoGI7qC3Xxq + q5g8EzJiYyTCOnI5LKRggn97wGg= ) +7QKPELF33JOK9BVJ7CKE99AHG40B0SH7.test. 600 IN NSEC3 1 0 10 - 94Q15K1V1VE5F87EI37T2B9A39EEC368 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + J4ObL3p4eN0jWh06M+rX2SSPANQoKfnosElB + KcKE7fLqEjKK7N6Yh6KUlbEP25tfeZ7W6GBJ + b7q6Nh0Ax8fYdc/6JVvmxcwWcx5Lw1TfITGB + ttFntJlbp1A8lwP3pn8Ksql1X2ogh78AsgTb + X5kmXVukC1oEzt98EAa/V/an8QA= ) +CS8M3UVG0UJDR6USBES4U9SNUGQI2RJE.test. 600 IN NSEC3 1 0 10 - ETEQB5V431INUIIE547FKSOF7O4DJ62J A RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + Vyd/2b0S15fACJ8TiPXKtScV9A/ZztVumZAm + o2S6jaVJKWik+8orDW+WiJ4/PEl26PK2m1uv + HD2beuUCHj9EnYkN/dzL3Bsc302qr9xqsh0q + VFS2moznoNG415ZV3vgYR7L9DAp43ZeFuw6I + 7sr21hLYLUeo31xBsJg7RlOL+4s= ) +ETEQB5V431INUIIE547FKSOF7O4DJ62J.test. 600 IN NSEC3 1 0 10 - F8G1MB0JUEU3FBI11CAVFIPGEA3POOIM + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + oOHs1eb3JYeOMOnzE2PS6NIXBNzSoTYPIxo/ + P0d/ihsLKra3yNJNPTlu4kf+FZoNYAGtMK/D + 6dZWFvtdswDdi2C5WSgsanuHqXq5Lr3A1nCe + cQI5PO4RrLymB+MtYg15CNKcnc0WmJO8deSR + WzNOarC+Iz1Xj3FkKDS4FFr+02Q= ) +94Q15K1V1VE5F87EI37T2B9A39EEC368.test. 600 IN NSEC3 1 0 10 - CS8M3UVG0UJDR6USBES4U9SNUGQI2RJE + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + K0PvN7YtHQ63x/x2yXXa2S9GBGuTNJywDZ8M + wyMSwytCb9mn4hnKD5mJHaXGTw3YX7usbnEO + ce6hiJdN/VhMfbRMOvUpgyblOj4kXiYVZY1a + SyycfugK/Hu1j4az7lIhhnnx58GChA6mg8Vx + 3Uz6cNDDCSTBTl09NyeUUrKWsHQ= ) +FBH6B0LHT9PPQB1P98D228HA1H52L8PO.test. 600 IN NSEC3 1 0 10 - JGU2L7C3LKLHAKC5RHUOORTI2DCKK3KL + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + giXRE+4ZeIzDrhx1XkFSpIKGFd3UGzlrLZnO + Ur9nMUfwvU5A3fitEkdayo3ZDH7MQGpSotaH + ReiFXx3Z6Hm2NIN/RHYZQr9e0vbMYSjkANdu + HWBA1SrSq5SHyuy970mPd4jfTHiABCo6fJGB + ykGClZGou0WSaB+Ak19fMbeQ2Wo= ) +JGU2L7C3LKLHAKC5RHUOORTI2DCKK3KL.test. 600 IN NSEC3 1 0 10 - KFMJ88CKMKUQQJE59IKFBOLLLD4DF55H TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + BHTDUgZdWNLgz3xHYMqvlWK/IJ0xrXESoREc + 6D3sO9bcLTMYPO9t80itOlipwp4AmaVOBXPt + cKSdgsUXDEtHqNSxtGbNr5xQ+Aqsep0GX71V + HkcIuiNdTUw83dkajCHMkmQCbEjp9mbdiTmS + haNW2EsscldfaS1aq5tYUhCT3l4= ) +L993U6VC0DUV5QJ8TRPD2IQLM8FJ7AT9.test. 600 IN NSEC3 1 0 10 - LSMRLLNBQGGK8J6V40KLM2LG5TE4FS0P + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + vE7K0Nrju4qLFDYkIyMY5bIMT0wu8MJdxL6u + 7WVA4HepccKQcUnvVoBAcrA9+MUeteyrad8Y + SJvQIt7sz5t7FViWSq5IMPVPujWtW5J30LhJ + mOLd1KmnFWoVthJ1oFNzBM80A60seKNnEw1M + lV6Y+v0gNYIQensUb9w6SVMTpxE= ) +F8G1MB0JUEU3FBI11CAVFIPGEA3POOIM.test. 600 IN NSEC3 1 0 10 - FA1T7MKUUV9SD4VDBJQ3GRFK1IDTCKL7 + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + DkL9ONc0vpsKdG20ol8XPAaVfLb7kf1wnKbR + rQUB1trGSHm/Igo06of43zm9J+56htFJg1xD + I2de0sCUBQYyHVBBDiBAd1g+ZvcpUlLP0w8M + NxMviMiG/WQAdGXHwYfUimwMWD7gNGl1m05H + HwYmzGs+d1bClDNBrFhdfdL2+iA= ) +LSMRLLNBQGGK8J6V40KLM2LG5TE4FS0P.test. 600 IN NSEC3 1 0 10 - LUAN2Q3I2OCVSD41MP08HNA9JP22D38K + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + ZgiWuMqodQuhwuAF6CIiJTsdRahi+poOiZAM + WXNP0wXfdptcG2uhbdDwy+0crhe3tuybhwcb + CuiaQUh0XNPhgF+qmXpGobaqBhCEvCF4K9qY + OCIoMfsI1pIBVbMw0+YXVarFZ8+mfNU/+6n6 + yy2+1nCg3k4XR2Dpv4CeDBfcAuM= ) +NAL1UIEBM38NKMN6RQOKE8T781IA7UKI.test. 600 IN NSEC3 1 0 10 - OUSGP0LO9FGAROHDULQVSTI3OLQIBB39 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + x8JiXPI+EXHz8ZO/VW0/+9wWsBNqeSMxXZIV + ibOnogSg7Wi7Yq1xftKC2+xEevNxSZnBibEy + Sgro5xKTf0n7pD9hHVBLoYmOOnbXY3QNQ2EQ + y3LdPT355WmwVddVOOxNpNRp2zQyqg7BhVA3 + wxY7tyVQd4x1+95ATUQBnFditdE= ) +KFMJ88CKMKUQQJE59IKFBOLLLD4DF55H.test. 600 IN NSEC3 1 0 10 - L993U6VC0DUV5QJ8TRPD2IQLM8FJ7AT9 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + KQPaN2Ecebifbl4Bz5Yo0x2DgGmZiVhpSydm + oy/5NtMjt7G472JrKlqByap+VxW0bpzo3IER + 3P8Dsv7pfBD4/Cl5sFqwZL7wYy7RB4dQLVCi + Pepc/Mr3gR2XmL91fpGttMj5jGscnVQJCyFa + obzhsVaVImUQZFDPb0UQUHwIhOA= ) +LUAN2Q3I2OCVSD41MP08HNA9JP22D38K.test. 600 IN NSEC3 1 0 10 - NAL1UIEBM38NKMN6RQOKE8T781IA7UKI TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + NJ+X3d0qh2+fbSnG0iQPxAeDIOzX5NTmY9fS + x7IO/DDcgUhPvl1YYdz5J999cec1zzOKp10J + YbsIAzg0w/Y4D4CBUw3IkcOrUFOODb6eJQGb + rVFRqmp3BUP4qOAWUZvx4oQ0KG4K/h/KJMbU + Vcdl7PF7G5O5hMyR9UWg4zal7Sk= ) +OUSGP0LO9FGAROHDULQVSTI3OLQIBB39.test. 600 IN NSEC3 1 0 10 - PQQ28M3U2MM08GGFV3JKR76G2H9IUJPC TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + A/qxYrSE/smBGbST8j8eGPCrRnwvVa25kDha + IuA3nv0vzXhFvlruc9f0HRGwsq6A2pw3I5W+ + xo2/JxsNyFOotdwaDDEBzqPkJmrzupxQS4Hm + rHSLnRnNw4QzvzNjAGWMYAoe3OeHC47wmAtI + qE91EHZTlPP28CUXOMo+7sCaOa8= ) +U0UVS2SUP89P2TM3PJO4TC1GPJ2O6519.test. 600 IN NSEC3 1 0 10 - VA2VG5BEMCKQP6MS5NHHGL18031BIA7M NS SOA RRSIG DNSKEY NSEC3PARAM + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + rahhkfiF+Rk6oqbWTdu9qcwhmj5hbDuIFdiJ + GmaG+cFSv5Mjp+txNVCvBK9Hq/VpW0ypen/3 + JC0sVAugSX+HAKAgyaMKmgWCvoQZ6ZSJUh7o + LRPcT+oxVXQAqjovxpaV8k6sYo44tpljPdOD + UluWAP5SrmJKjzCxs27KGRx8MK4= ) +VA2VG5BEMCKQP6MS5NHHGL18031BIA7M.test. 600 IN NSEC3 1 0 10 - VAKOQ2TPD7S25NFBJT73J3C4OGU10RJ5 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + XcBeZ8lo9Qo8z56+1FdGDjh6ZHCfO+MQ/wnY + TEUo/aWLkPTyq39nLhe0qVBJxmDpM+KQFuG9 + cjQT5fvrlrY+lv6dedB64EBMYy4kKbIv7N5+ + r6+sfWlvtKsfXxysLSk2+jLEm5NuLFrOdNas + WLVsq741D3YcWt4kM1HCyk3DNF8= ) +FA1T7MKUUV9SD4VDBJQ3GRFK1IDTCKL7.test. 600 IN NSEC3 1 0 10 - FBH6B0LHT9PPQB1P98D228HA1H52L8PO TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + jB/vLrvx4sQQD7J3ZacAAyhcFmIPh7LH3ljw + IAIaeLb10oX5q1/nQKYdfq976TMy5sWpBcmd + i91WLxd+T/gOSumyP8bC3g+SUoyZ9wxY6A6a + MMx1rn0QA9IKrxMqojs9M3urJ8QAeIS+KyAn + rbyyJuG+EVm0prqlPZtzUi28WCI= ) +PQQ28M3U2MM08GGFV3JKR76G2H9IUJPC.test. 600 IN NSEC3 1 0 10 - U0UVS2SUP89P2TM3PJO4TC1GPJ2O6519 + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + asCOU9OkVWMvUU2IUpwMgdYf0faA04zPbaFf + qywYsv3NH01Lky6G3a0WUPAbBm7TAYx/ln8a + 559vlpp/gpXEl9CcLrjO6wy5i0ryp8gVHtKJ + rQlEc/uw4SY+S5t7FuZc2rNRdAbxVMYuwrvm + HBsKDPblre3e06ZZFEmnGFzCgmg= ) +VAKOQ2TPD7S25NFBJT73J3C4OGU10RJ5.test. 600 IN NSEC3 1 0 10 - VNCCJH8JPOLGLAGVMV3FKS09M7RRDU47 TXT RRSIG + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + Pt4tKB1p/jsyLYab9LSt5MF1KTRT18nRTOox + q0IACkXkKx7W5xv6nSYXIB+nQzNp1Y1hhoXn + 9IFi0liPnIAOp73w4vybhfIdTFiEmHPHT6O9 + VIx5cSriqBI6Qda8GtfeIb96P8SojbUk5BDI + g18iYjviGhQYRgpU3tg1qd7pbcc= ) +VNCCJH8JPOLGLAGVMV3FKS09M7RRDU47.test. 600 IN NSEC3 1 0 10 - 1F3JQ6EANHNHOCMUPQTVNM339VDTR51C + 600 RRSIG NSEC3 7 2 600 20110914225156 ( + 20110815225156 39833 test. + ZMZPHawhkuzSV7C7zkgghH/jpw9CQVR1JUXq + pAeY2iIIWwNhfuskJaLgtu/5SuKnJtrv6D4N + g+lfEkBReia5xO/SCcHv8/hXEPH8vZ4xe1C9 + 6GVB6ip2hKw2g5HpyF7X18WgwZ0cqPWVg+Q+ + xRLpXH+53391Wt5rG7qJswn5RLE= ) diff --git a/tests/dns/testdata/diff/zone1.data b/tests/dns/testdata/diff/zone1.data new file mode 100644 index 0000000..8ddf669 --- /dev/null +++ b/tests/dns/testdata/diff/zone1.data @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 diff --git a/tests/dns/testdata/diff/zone2.data b/tests/dns/testdata/diff/zone2.data new file mode 100644 index 0000000..363af42 --- /dev/null +++ b/tests/dns/testdata/diff/zone2.data @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 +remove 0 A 5.6.7.8 +added 0 A 5.6.7.8 diff --git a/tests/dns/testdata/diff/zone3.data b/tests/dns/testdata/diff/zone3.data new file mode 100644 index 0000000..ae3a60e --- /dev/null +++ b/tests/dns/testdata/diff/zone3.data @@ -0,0 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS @ +@ 0 A 1.2.3.4 diff --git a/tests/dns/testdata/dnstap/dnstap.saved b/tests/dns/testdata/dnstap/dnstap.saved Binary files differnew file mode 100644 index 0000000..c657f41 --- /dev/null +++ b/tests/dns/testdata/dnstap/dnstap.saved diff --git a/tests/dns/testdata/dnstap/dnstap.text b/tests/dns/testdata/dnstap/dnstap.text new file mode 100644 index 0000000..71977e4 --- /dev/null +++ b/tests/dns/testdata/dnstap/dnstap.text @@ -0,0 +1,96 @@ +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 SR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 CR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 AR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 RR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 FR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 UDP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 15:47:16.000 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TQ 10.53.0.1:2112 -> 10.53.0.2:2112 TCP 40b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 UDP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 17:47:16.000 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A +03-Feb-2017 16:47:16.830 TR 10.53.0.1:2112 <- 10.53.0.2:2112 TCP 287b www.isc.org/IN/A diff --git a/tests/dns/testdata/dnstap/query.auth b/tests/dns/testdata/dnstap/query.auth new file mode 100644 index 0000000..a14f850 --- /dev/null +++ b/tests/dns/testdata/dnstap/query.auth @@ -0,0 +1,4 @@ +# authoritative query, www.isc.org/A +8d 24 00 20 00 01 00 00 00 00 00 01 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 00 00 29 +10 00 00 00 00 00 00 00 diff --git a/tests/dns/testdata/dnstap/query.recursive b/tests/dns/testdata/dnstap/query.recursive new file mode 100644 index 0000000..8ee705f --- /dev/null +++ b/tests/dns/testdata/dnstap/query.recursive @@ -0,0 +1,4 @@ +# recursive query for www.isc.org/A +bf 08 01 20 00 01 00 00 00 00 00 01 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 00 00 29 +10 00 00 00 00 00 00 00 diff --git a/tests/dns/testdata/dnstap/response.auth b/tests/dns/testdata/dnstap/response.auth new file mode 100644 index 0000000..4d0ea81 --- /dev/null +++ b/tests/dns/testdata/dnstap/response.auth @@ -0,0 +1,19 @@ +# authoritative response, www.isc.org/A +8d 24 84 00 00 01 00 01 00 04 00 07 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 c0 0c 00 +01 00 01 00 00 00 3c 00 04 95 14 40 45 c0 10 00 +02 00 01 00 00 1c 20 00 0d 03 61 6d 73 06 73 6e +73 2d 70 62 c0 10 c0 10 00 02 00 01 00 00 1c 20 +00 07 04 73 66 62 61 c0 3d c0 10 00 02 00 01 00 +00 1c 20 00 19 02 6e 73 03 69 73 63 0b 61 66 69 +6c 69 61 73 2d 6e 73 74 04 69 6e 66 6f 00 c0 10 +00 02 00 01 00 00 1c 20 00 06 03 6f 72 64 c0 3d +c0 39 00 01 00 01 00 00 1c 20 00 04 c7 06 01 1e +c0 39 00 1c 00 01 00 00 1c 20 00 10 20 01 05 00 +00 60 00 00 00 00 00 00 00 00 00 30 c0 8a 00 01 +00 01 00 00 1c 20 00 04 c7 06 00 1e c0 8a 00 1c +00 01 00 00 1c 20 00 10 20 01 05 00 00 71 00 00 +00 00 00 00 00 00 00 30 c0 52 00 01 00 01 00 00 +1c 20 00 04 95 14 40 03 c0 52 00 1c 00 01 00 00 +1c 20 00 10 20 01 04 f8 00 00 00 02 00 00 00 00 +00 00 00 19 00 00 29 10 00 00 00 00 00 00 00 diff --git a/tests/dns/testdata/dnstap/response.recursive b/tests/dns/testdata/dnstap/response.recursive new file mode 100644 index 0000000..6e3a3cf --- /dev/null +++ b/tests/dns/testdata/dnstap/response.recursive @@ -0,0 +1,19 @@ +# recursive response, www.isc.org/A +bf 08 81 a0 00 01 00 01 00 04 00 07 03 77 77 77 +03 69 73 63 03 6f 72 67 00 00 01 00 01 c0 0c 00 +01 00 01 00 00 00 15 00 04 95 14 40 45 c0 10 00 +02 00 01 00 00 1b a6 00 0e 04 73 66 62 61 06 73 +6e 73 2d 70 62 c0 10 c0 10 00 02 00 01 00 00 1b +a6 00 06 03 6f 72 64 c0 3e c0 10 00 02 00 01 00 +00 1b a6 00 19 02 6e 73 03 69 73 63 0b 61 66 69 +6c 69 61 73 2d 6e 73 74 04 69 6e 66 6f 00 c0 10 +00 02 00 01 00 00 1b a6 00 06 03 61 6d 73 c0 3e +c0 8a 00 01 00 01 00 00 b1 d5 00 04 c7 06 01 1e +c0 8a 00 1c 00 01 00 00 b1 d5 00 10 20 01 05 00 +00 60 00 00 00 00 00 00 00 00 00 30 c0 53 00 01 +00 01 00 00 b1 d5 00 04 c7 06 00 1e c0 53 00 1c +00 01 00 00 b1 d5 00 10 20 01 05 00 00 71 00 00 +00 00 00 00 00 00 00 30 c0 39 00 01 00 01 00 00 +b1 d5 00 04 95 14 40 03 c0 39 00 1c 00 01 00 00 +b1 d5 00 10 20 01 04 f8 00 00 00 02 00 00 00 00 +00 00 00 19 00 00 29 10 00 00 00 00 00 00 00 diff --git a/tests/dns/testdata/dst/Ktest.+008+11349.key b/tests/dns/testdata/dst/Ktest.+008+11349.key new file mode 100644 index 0000000..a1bd768 --- /dev/null +++ b/tests/dns/testdata/dst/Ktest.+008+11349.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 11349, for test. +; Created: 20181025090713 (Thu Oct 25 11:07:13 2018) +; Publish: 20181025090713 (Thu Oct 25 11:07:13 2018) +; Activate: 20181025090713 (Thu Oct 25 11:07:13 2018) +test. IN DNSKEY 256 3 8 AwEAAdqPwPScyURzeCUzEadKNYgQW50LPDV/ir9nWIbiSn2yMkymxiby BQH+Hk1neE9qa9X4XaEnKf5YZx7o14rRikmOb2lomtOkI9ovh1K/SvLO Zd1E3e61F29g1eCq52mMY3xAdEcBNqEq+6mgEwGmwl83+mAh5anxXNHa 2rcfdG+L diff --git a/tests/dns/testdata/dst/Ktest.+008+11349.private b/tests/dns/testdata/dst/Ktest.+008+11349.private new file mode 100644 index 0000000..5dfef79 --- /dev/null +++ b/tests/dns/testdata/dst/Ktest.+008+11349.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 2o/A9JzJRHN4JTMRp0o1iBBbnQs8NX+Kv2dYhuJKfbIyTKbGJvIFAf4eTWd4T2pr1fhdoScp/lhnHujXitGKSY5vaWia06Qj2i+HUr9K8s5l3UTd7rUXb2DV4KrnaYxjfEB0RwE2oSr7qaATAabCXzf6YCHlqfFc0dratx90b4s= +PublicExponent: AQAB +PrivateExponent: a4qmX/YxlmvWpz8spYr/MhcSbQCVPKGoLKv2RFBeZODknRDGmW0mh6d5U47hBPqRWvRdZak2oX7wJqZdQGIAT25bC09rLNMctfxXKtzwSaXFjXZGHGv+bDHcqIltvIYmRbb0pK/LinFaLZqfpVe0WOfKuT9BT03BlwSZV8GKgZE= +Prime1: 8oZLQoVpIqsiQw7bX5pTm/O0gEUnEzNOVEoLGsfIl68Lz/1CBm9ypTp8QOB0B9IpnH8vOS+NJM1az1d0RhqKow== +Prime2: 5rSbE6duWIb90uICkAUJn4OztHX0fkd9GKNYdsHVReFBH2poXGojVGkW6i/IaYl4NEXXr5Z89dWtR+RNH2Z9+Q== +Exponent1: 2IcuCmYyR9Gi9Vv+YIzYuRQMw7j5+hqEhJzW7UIRxdtzIG9s03INWZet9/5tmc35eM/Uyam6ynDN8vCRz0VDIQ== +Exponent2: vKcdVKIKWrvwXXzRaaGk79rLnZsDFiwxQG96TIpOczkyfpUNx9xHDaRtx4zRTnPKZrxiFkRx5LkZXHt1EWNHSQ== +Coefficient: pb9dFRZA2IRXDCGCM1ikp+QCs72wNn3hgURZLRLmtcBbQcYhP/dcp80SpInviwJPNRcKrfxninqygEARzfHtqQ== +Created: 20181025090713 +Publish: 20181025090713 +Activate: 20181025090713 diff --git a/tests/dns/testdata/dst/Ktest.+013+49130.key b/tests/dns/testdata/dst/Ktest.+013+49130.key new file mode 100644 index 0000000..e3ff931 --- /dev/null +++ b/tests/dns/testdata/dst/Ktest.+013+49130.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 49130, for test. +; Created: 20181025090718 (Thu Oct 25 11:07:18 2018) +; Publish: 20181025090718 (Thu Oct 25 11:07:18 2018) +; Activate: 20181025090718 (Thu Oct 25 11:07:18 2018) +test. IN DNSKEY 256 3 13 uP04fwB/DuBBqdjPLseIoFT7vgtP8Lr/be1NhRBvibwQ+Hr+3GQhIKIK XbamgOUxXJ9JDjWFAT2KXw0V3sAN9w== diff --git a/tests/dns/testdata/dst/Ktest.+013+49130.private b/tests/dns/testdata/dst/Ktest.+013+49130.private new file mode 100644 index 0000000..754d9f9 --- /dev/null +++ b/tests/dns/testdata/dst/Ktest.+013+49130.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: feGDRABRCbcsCqssKK5B5518y95smrv/cJnz2pa/UVA= +Created: 20181025090718 +Publish: 20181025090718 +Activate: 20181025090718 diff --git a/tests/dns/testdata/dst/test1.data b/tests/dns/testdata/dst/test1.data new file mode 100644 index 0000000..cf84e9f --- /dev/null +++ b/tests/dns/testdata/dst/test1.data @@ -0,0 +1,3077 @@ +Network Working Group P. Mockapetris +Request for Comments: 1035 ISI + November 1987 +Obsoletes: RFCs 882, 883, 973 + + DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION + + +1. STATUS OF THIS MEMO + +This RFC describes the details of the domain system and protocol, and +assumes that the reader is familiar with the concepts discussed in a +companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034]. + +The domain system is a mixture of functions and data types which are an +official protocol and functions and data types which are still +experimental. Since the domain system is intentionally extensible, new +data types and experimental behavior should always be expected in parts +of the system beyond the official protocol. The official protocol parts +include standard queries, responses and the Internet class RR data +formats (e.g., host addresses). Since the previous RFC set, several +definitions have changed, so some previous definitions are obsolete. + +Experimental or obsolete features are clearly marked in these RFCs, and +such information should be used with caution. + +The reader is especially cautioned not to depend on the values which +appear in examples to be current or complete, since their purpose is +primarily pedagogical. Distribution of this memo is unlimited. + + Table of Contents + + 1. STATUS OF THIS MEMO 1 + 2. INTRODUCTION 3 + 2.1. Overview 3 + 2.2. Common configurations 4 + 2.3. Conventions 7 + 2.3.1. Preferred name syntax 7 + 2.3.2. Data Transmission Order 8 + 2.3.3. Character Case 9 + 2.3.4. Size limits 10 + 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 + 3.1. Name space definitions 10 + 3.2. RR definitions 11 + 3.2.1. Format 11 + 3.2.2. TYPE values 12 + 3.2.3. QTYPE values 12 + 3.2.4. CLASS values 13 + + + +Mockapetris [Page 1] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 3.2.5. QCLASS values 13 + 3.3. Standard RRs 13 + 3.3.1. CNAME RDATA format 14 + 3.3.2. HINFO RDATA format 14 + 3.3.3. MB RDATA format (EXPERIMENTAL) 14 + 3.3.4. MD RDATA format (Obsolete) 15 + 3.3.5. MF RDATA format (Obsolete) 15 + 3.3.6. MG RDATA format (EXPERIMENTAL) 16 + 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 + 3.3.8. MR RDATA format (EXPERIMENTAL) 17 + 3.3.9. MX RDATA format 17 + 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 + 3.3.11. NS RDATA format 18 + 3.3.12. PTR RDATA format 18 + 3.3.13. SOA RDATA format 19 + 3.3.14. TXT RDATA format 20 + 3.4. ARPA Internet specific RRs 20 + 3.4.1. A RDATA format 20 + 3.4.2. WKS RDATA format 21 + 3.5. IN-ADDR.ARPA domain 22 + 3.6. Defining new types, classes, and special namespaces 24 + 4. MESSAGES 25 + 4.1. Format 25 + 4.1.1. Header section format 26 + 4.1.2. Question section format 28 + 4.1.3. Resource record format 29 + 4.1.4. Message compression 30 + 4.2. Transport 32 + 4.2.1. UDP usage 32 + 4.2.2. TCP usage 32 + 5. MASTER FILES 33 + 5.1. Format 33 + 5.2. Use of master files to define zones 35 + 5.3. Master file example 36 + 6. NAME SERVER IMPLEMENTATION 37 + 6.1. Architecture 37 + 6.1.1. Control 37 + 6.1.2. Database 37 + 6.1.3. Time 39 + 6.2. Standard query processing 39 + 6.3. Zone refresh and reload processing 39 + 6.4. Inverse queries (Optional) 40 + 6.4.1. The contents of inverse queries and responses 40 + 6.4.2. Inverse query and response example 41 + 6.4.3. Inverse query processing 42 + + + + + + +Mockapetris [Page 2] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 6.5. Completion queries and responses 42 + 7. RESOLVER IMPLEMENTATION 43 + 7.1. Transforming a user request into a query 43 + 7.2. Sending the queries 44 + 7.3. Processing responses 46 + 7.4. Using the cache 47 + 8. MAIL SUPPORT 47 + 8.1. Mail exchange binding 48 + 8.2. Mailbox binding (Experimental) 48 + 9. REFERENCES and BIBLIOGRAPHY 50 + Index 54 + +2. INTRODUCTION + +2.1. Overview + +The goal of domain names is to provide a mechanism for naming resources +in such a way that the names are usable in different hosts, networks, +protocol families, internets, and administrative organizations. + +From the user's point of view, domain names are useful as arguments to a +local agent, called a resolver, which retrieves information associated +with the domain name. Thus a user might ask for the host address or +mail information associated with a particular domain name. To enable +the user to request a particular type of information, an appropriate +query type is passed to the resolver with the domain name. To the user, +the domain tree is a single information space; the resolver is +responsible for hiding the distribution of data among name servers from +the user. + +From the resolver's point of view, the database that makes up the domain +space is distributed among various name servers. Different parts of the +domain space are stored in different name servers, although a particular +data item will be stored redundantly in two or more name servers. The +resolver starts with knowledge of at least one name server. When the +resolver processes a user query it asks a known name server for the +information; in return, the resolver either receives the desired +information or a referral to another name server. Using these +referrals, resolvers learn the identities and contents of other name +servers. Resolvers are responsible for dealing with the distribution of +the domain space and dealing with the effects of name server failure by +consulting redundant databases in other servers. + +Name servers manage two kinds of data. The first kind of data held in +sets called zones; each zone is the complete database for a particular +"pruned" subtree of the domain space. This data is called +authoritative. A name server periodically checks to make sure that its +zones are up to date, and if not, obtains a new copy of updated zones + + + +Mockapetris [Page 3] + +RFC 1035 Domain Implementation and Specification November 1987 + + +from master files stored locally or in another name server. The second +kind of data is cached data which was acquired by a local resolver. +This data may be incomplete, but improves the performance of the +retrieval process when non-local data is repeatedly accessed. Cached +data is eventually discarded by a timeout mechanism. + +This functional structure isolates the problems of user interface, +failure recovery, and distribution in the resolvers and isolates the +database update and refresh problems in the name servers. + +2.2. Common configurations + +A host can participate in the domain name system in a number of ways, +depending on whether the host runs programs that retrieve information +from the domain system, name servers that answer queries from other +hosts, or various combinations of both functions. The simplest, and +perhaps most typical, configuration is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | cache | | + +----------+ | + +User programs interact with the domain name space through resolvers; the +format of user queries and user responses is specific to the host and +its operating system. User queries will typically be operating system +calls, and the resolver and its cache will be part of the host operating +system. Less capable hosts may choose to implement the resolver as a +subroutine to be linked in with every program that needs its services. +Resolvers answer user queries with information they acquire via queries +to foreign name servers and the local cache. + +Note that the resolver may have to make several queries to several +different foreign name servers to answer a particular user query, and +hence the resolution of a user query may involve several network +accesses and an arbitrary amount of time. The queries to foreign name +servers and the corresponding responses have a standard format described + + + +Mockapetris [Page 4] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in this memo, and may be datagrams. + +Depending on its capabilities, a name server could be a stand alone +program on a dedicated machine or a process or processes on a large +timeshared host. A simple configuration might be: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + +Here a primary name server acquires information about one or more zones +by reading master files from its local file system, and answers queries +about those zones that arrive from foreign resolvers. + +The DNS requires that all zones be redundantly supported by more than +one name server. Designated secondary servers can acquire zones and +check for updates from the primary server using the zone transfer +protocol of the DNS. This configuration is shown below: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +In this configuration, the name server periodically establishes a +virtual circuit to a foreign name server to acquire a copy of a zone or +to check that an existing copy has not changed. The messages sent for + + + +Mockapetris [Page 5] + +RFC 1035 Domain Implementation and Specification November 1987 + + +these maintenance activities follow the same form as queries and +responses, but the message sequences are somewhat different. + +The information flow in a host that supports all aspects of the domain +name system is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | Shared | | + | database | | + +----------+ | + A | | + +---------+ refreshes | | references | + / /| | V | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +The shared database holds domain space data for the local name server +and resolver. The contents of the shared database will typically be a +mixture of authoritative data maintained by the periodic refresh +operations of the name server and cached data from previous resolver +requests. The structure of the domain data and the necessity for +synchronization between name servers and resolvers imply the general +characteristics of this database, but the actual format is up to the +local implementor. + + + + +Mockapetris [Page 6] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Information flow can also be tailored so that a group of hosts act +together to optimize activities. Sometimes this is done to offload less +capable hosts so that they do not have to implement a full resolver. +This can be appropriate for PCs or hosts which want to minimize the +amount of new network code which is required. This scheme can also +allow a group of hosts can share a small number of caches rather than +maintaining a large number of separate caches, on the premise that the +centralized caches will have a higher hit ratio. In either case, +resolvers are replaced with stub resolvers which act as front ends to +resolvers located in a recursive server in one or more name servers +known to perform that service: + + Local Hosts | Foreign + | + +---------+ | + | | responses | + | Stub |<--------------------+ | + | Resolver| | | + | |----------------+ | | + +---------+ recursive | | | + queries | | | + V | | + +---------+ recursive +----------+ | +--------+ + | | queries | |queries | | | + | Stub |-------------->| Recursive|---------|->|Foreign | + | Resolver| | Server | | | Name | + | |<--------------| |<--------|--| Server | + +---------+ responses | |responses| | | + +----------+ | +--------+ + | Central | | + | cache | | + +----------+ | + +In any case, note that domain components are always replicated for +reliability whenever possible. + +2.3. Conventions + +The domain system has several conventions dealing with low-level, but +fundamental, issues. While the implementor is free to violate these +conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in +ALL behavior observed from other hosts. + +2.3.1. Preferred name syntax + +The DNS specifications attempt to be as general as possible in the rules +for constructing domain names. The idea is that the name of any +existing object can be expressed as a domain name with minimal changes. + + + +Mockapetris [Page 7] + +RFC 1035 Domain Implementation and Specification November 1987 + + +However, when assigning a domain name for an object, the prudent user +will select a name which satisfies both the rules of the domain system +and any existing rules for the object, whether these rules are published +or implied by existing programs. + +For example, when naming a mail domain, the user should satisfy both the +rules of this memo and those in RFC-822. When creating a new host name, +the old rules for HOSTS.TXT should be followed. This avoids problems +when old software is converted to use domain names. + +The following syntax will result in fewer problems with many + +applications that use domain names (e.g., mail, TELNET). + +<domain> ::= <subdomain> | " " + +<subdomain> ::= <label> | <subdomain> "." <label> + +<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ] + +<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str> + +<let-dig-hyp> ::= <let-dig> | "-" + +<let-dig> ::= <letter> | <digit> + +<letter> ::= any one of the 52 alphabetic characters A through Z in +upper case and a through z in lower case + +<digit> ::= any one of the ten digits 0 through 9 + +Note that while upper and lower case letters are allowed in domain +names, no significance is attached to the case. That is, two names with +the same spelling but different case are to be treated as if identical. + +The labels must follow the rules for ARPANET host names. They must +start with a letter, end with a letter or digit, and have as interior +characters only letters, digits, and hyphen. There are also some +restrictions on the length. Labels must be 63 characters or less. + +For example, the following strings identify hosts in the Internet: + +A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA + +2.3.2. Data Transmission Order + +The order of transmission of the header and data described in this +document is resolved to the octet level. Whenever a diagram shows a + + + +Mockapetris [Page 8] + +RFC 1035 Domain Implementation and Specification November 1987 + + +group of octets, the order of transmission of those octets is the normal +order in which they are read in English. For example, in the following +diagram, the octets are transmitted in the order they are numbered. + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 1 | 2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 3 | 4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 5 | 6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Whenever an octet represents a numeric quantity, the left most bit in +the diagram is the high order or most significant bit. That is, the bit +labeled 0 is the most significant bit. For example, the following +diagram represents the value 170 (decimal). + + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |1 0 1 0 1 0 1 0| + +-+-+-+-+-+-+-+-+ + +Similarly, whenever a multi-octet field represents a numeric quantity +the left most bit of the whole field is the most significant bit. When +a multi-octet quantity is transmitted the most significant octet is +transmitted first. + +2.3.3. Character Case + +For all parts of the DNS that are part of the official protocol, all +comparisons between character strings (e.g., labels, domain names, etc.) +are done in a case-insensitive manner. At present, this rule is in +force throughout the domain system without exception. However, future +additions beyond current usage may need to use the full binary octet +capabilities in names, so attempts to store domain names in 7-bit ASCII +or use of special bytes to terminate labels, etc., should be avoided. + +When data enters the domain system, its original case should be +preserved whenever possible. In certain circumstances this cannot be +done. For example, if two RRs are stored in a database, one at x.y and +one at X.Y, they are actually stored at the same place in the database, +and hence only one casing would be preserved. The basic rule is that +case can be discarded only when data is used to define structure in a +database, and two names are identical when compared in a case +insensitive manner. + + + + +Mockapetris [Page 9] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Loss of case sensitive data must be minimized. Thus while data for x.y +and X.Y may both be stored under a single location x.y or X.Y, data for +a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In +general, this preserves the case of the first label of a domain name, +but forces standardization of interior node labels. + +Systems administrators who enter data into the domain database should +take care to represent the data they supply to the domain system in a +case-consistent manner if their system is case-sensitive. The data +distribution system in the domain system will ensure that consistent +representations are preserved. + +2.3.4. Size limits + +Various objects and parameters in the DNS have size limits. They are +listed below. Some could be easily changed, others are more +fundamental. + +labels 63 octets or less + +names 255 octets or less + +TTL positive values of a signed 32 bit number. + +UDP messages 512 octets or less + +3. DOMAIN NAME SPACE AND RR DEFINITIONS + +3.1. Name space definitions + +Domain names in messages are expressed in terms of a sequence of labels. +Each label is represented as a one octet length field followed by that +number of octets. Since every domain name ends with the null label of +the root, a domain name is terminated by a length byte of zero. The +high order two bits of every length octet must be zero, and the +remaining six bits of the length field limit the label to 63 octets or +less. + +To simplify implementations, the total length of a domain name (i.e., +label octets and label length octets) is restricted to 255 octets or +less. + +Although labels can contain any 8 bit values in octets that make up a +label, it is strongly recommended that labels follow the preferred +syntax described elsewhere in this memo, which is compatible with +existing host naming conventions. Name servers and resolvers must +compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII +with zero parity. Non-alphabetic codes must match exactly. + + + +Mockapetris [Page 10] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.2. RR definitions + +3.2.1. Format + +All RRs have the same top level format shown below: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +where: + +NAME an owner name, i.e., the name of the node to which this + resource record pertains. + +TYPE two octets containing one of the RR TYPE codes. + +CLASS two octets containing one of the RR CLASS codes. + +TTL a 32 bit signed integer that specifies the time interval + that the resource record may be cached before the source + of the information should again be consulted. Zero + values are interpreted to mean that the RR can only be + used for the transaction in progress, and should not be + cached. For example, SOA records are always distributed + with a zero TTL to prohibit caching. Zero values can + also be used for extremely volatile data. + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + + + +Mockapetris [Page 11] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + +3.2.2. TYPE values + +TYPE fields are used in resource records. Note that these types are a +subset of QTYPEs. + +TYPE value and meaning + +A 1 a host address + +NS 2 an authoritative name server + +MD 3 a mail destination (Obsolete - use MX) + +MF 4 a mail forwarder (Obsolete - use MX) + +CNAME 5 the canonical name for an alias + +SOA 6 marks the start of a zone of authority + +MB 7 a mailbox domain name (EXPERIMENTAL) + +MG 8 a mail group member (EXPERIMENTAL) + +MR 9 a mail rename domain name (EXPERIMENTAL) + +NULL 10 a null RR (EXPERIMENTAL) + +WKS 11 a well known service description + +PTR 12 a domain name pointer + +HINFO 13 host information + +MINFO 14 mailbox or mail list information + +MX 15 mail exchange + +TXT 16 text strings + +3.2.3. QTYPE values + +QTYPE fields appear in the question part of a query. QTYPES are a +superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the +following QTYPEs are defined: + + + +Mockapetris [Page 12] + +RFC 1035 Domain Implementation and Specification November 1987 + + +AXFR 252 A request for a transfer of an entire zone + +MAILB 253 A request for mailbox-related records (MB, MG or MR) + +MAILA 254 A request for mail agent RRs (Obsolete - see MX) + +* 255 A request for all records + +3.2.4. CLASS values + +CLASS fields appear in resource records. The following CLASS mnemonics +and values are defined: + +IN 1 the Internet + +CS 2 the CSNET class (Obsolete - used only for examples in + some obsolete RFCs) + +CH 3 the CHAOS class + +HS 4 Hesiod [Dyer 87] + +3.2.5. QCLASS values + +QCLASS fields appear in the question section of a query. QCLASS values +are a superset of CLASS values; every CLASS is a valid QCLASS. In +addition to CLASS values, the following QCLASSes are defined: + +* 255 any class + +3.3. Standard RRs + +The following RR definitions are expected to occur, at least +potentially, in all classes. In particular, NS, SOA, CNAME, and PTR +will be used in all classes, and have the same format in all classes. +Because their RDATA format is known, all domain names in the RDATA +section of these RRs may be compressed. + +<domain-name> is a domain name represented as a series of labels, and +terminated by a label with zero length. <character-string> is a single +length octet followed by that number of characters. <character-string> +is treated as binary information, and can be up to 256 characters in +length (including the length octet). + + + + + + + + +Mockapetris [Page 13] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.1. CNAME RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CNAME A <domain-name> which specifies the canonical or primary + name for the owner. The owner name is an alias. + +CNAME RRs cause no additional section processing, but name servers may +choose to restart the query at the canonical name in certain cases. See +the description of name server logic in [RFC-1034] for details. + +3.3.2. HINFO RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CPU / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / OS / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CPU A <character-string> which specifies the CPU type. + +OS A <character-string> which specifies the operating + system type. + +Standard values for CPU and OS can be found in [RFC-1010]. + +HINFO records are used to acquire general information about a host. The +main use is for protocols such as FTP that can use special procedures +when talking between machines or operating systems of the same type. + +3.3.3. MB RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has the + specified mailbox. + + + +Mockapetris [Page 14] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MB records cause additional section processing which looks up an A type +RRs corresponding to MADNAME. + +3.3.4. MD RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which should be able to deliver + mail for the domain. + +MD records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MD is obsolete. See the definition of MX and [RFC-974] for details of +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 0. + +3.3.5. MF RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which will accept mail for + forwarding to the domain. + +MF records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MF is obsolete. See the definition of MX and [RFC-974] for details ofw +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 10. + + + + + + + +Mockapetris [Page 15] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.6. MG RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MGMNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MGMNAME A <domain-name> which specifies a mailbox which is a + member of the mail group specified by the domain name. + +MG records cause no additional section processing. + +3.3.7. MINFO RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +RMAILBX A <domain-name> which specifies a mailbox which is + responsible for the mailing list or mailbox. If this + domain name names the root, the owner of the MINFO RR is + responsible for itself. Note that many existing mailing + lists use a mailbox X-request for the RMAILBX field of + mailing list X, e.g., Msgroup-request for Msgroup. This + field provides a more general mechanism. + + +EMAILBX A <domain-name> which specifies a mailbox which is to + receive error messages related to the mailing list or + mailbox specified by the owner of the MINFO RR (similar + to the ERRORS-TO: field which has been proposed). If + this domain name names the root, errors should be + returned to the sender of the message. + +MINFO records cause no additional section processing. Although these +records can be associated with a simple mailbox, they are usually used +with a mailing list. + + + + + + + + +Mockapetris [Page 16] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.8. MR RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NEWNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NEWNAME A <domain-name> which specifies a mailbox which is the + proper rename of the specified mailbox. + +MR records cause no additional section processing. The main use for MR +is as a forwarding entry for a user who has moved to a different +mailbox. + +3.3.9. MX RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PREFERENCE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EXCHANGE / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PREFERENCE A 16 bit integer which specifies the preference given to + this RR among others at the same owner. Lower values + are preferred. + +EXCHANGE A <domain-name> which specifies a host willing to act as + a mail exchange for the owner name. + +MX records cause type A additional section processing for the host +specified by EXCHANGE. The use of MX RRs is explained in detail in +[RFC-974]. + +3.3.10. NULL RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / <anything> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +Anything at all may be in the RDATA field so long as it is 65535 octets +or less. + + + + +Mockapetris [Page 17] + +RFC 1035 Domain Implementation and Specification November 1987 + + +NULL records cause no additional section processing. NULL RRs are not +allowed in master files. NULLs are used as placeholders in some +experimental extensions of the DNS. + +3.3.11. NS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NSDNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NSDNAME A <domain-name> which specifies a host which should be + authoritative for the specified class and domain. + +NS records cause both the usual additional section processing to locate +a type A record, and, when used in a referral, a special search of the +zone in which they reside for glue information. + +The NS RR states that the named host should be expected to have a zone +starting at owner name of the specified class. Note that the class may +not indicate the protocol family which should be used to communicate +with the host, although it is typically a strong hint. For example, +hosts which are name servers for either Internet (IN) or Hesiod (HS) +class information are normally queried using IN class protocols. + +3.3.12. PTR RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / PTRDNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PTRDNAME A <domain-name> which points to some location in the + domain name space. + +PTR records cause no additional section processing. These RRs are used +in special domains to point to some other location in the domain space. +These records are simple data, and don't imply any special processing +similar to that performed by CNAME, which identifies aliases. See the +description of the IN-ADDR.ARPA domain for an example. + + + + + + + + +Mockapetris [Page 18] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.13. SOA RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | SERIAL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | REFRESH | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RETRY | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | EXPIRE | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | MINIMUM | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MNAME The <domain-name> of the name server that was the + original or primary source of data for this zone. + +RNAME A <domain-name> which specifies the mailbox of the + person responsible for this zone. + +SERIAL The unsigned 32 bit version number of the original copy + of the zone. Zone transfers preserve this value. This + value wraps and should be compared using sequence space + arithmetic. + +REFRESH A 32 bit time interval before the zone should be + refreshed. + +RETRY A 32 bit time interval that should elapse before a + failed refresh should be retried. + +EXPIRE A 32 bit time value that specifies the upper limit on + the time interval that can elapse before the zone is no + longer authoritative. + + + + + +Mockapetris [Page 19] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MINIMUM The unsigned 32 bit minimum TTL field that should be + exported with any RR from this zone. + +SOA records cause no additional section processing. + +All times are in units of seconds. + +Most of these fields are pertinent only for name server maintenance +operations. However, MINIMUM is used in all query operations that +retrieve RRs from a zone. Whenever a RR is sent in a response to a +query, the TTL field is set to the maximum of the TTL field from the RR +and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower +bound on the TTL field for all RRs in a zone. Note that this use of +MINIMUM should occur when the RRs are copied into the response and not +when the zone is loaded from a master file or via a zone transfer. The +reason for this provison is to allow future dynamic update facilities to +change the SOA RR with known semantics. + + +3.3.14. TXT RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / TXT-DATA / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +TXT-DATA One or more <character-string>s. + +TXT RRs are used to hold descriptive text. The semantics of the text +depends on the domain where it is found. + +3.4. Internet specific RRs + +3.4.1. A RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS A 32 bit Internet address. + +Hosts that have multiple Internet addresses will have multiple A +records. + + + + + +Mockapetris [Page 20] + +RFC 1035 Domain Implementation and Specification November 1987 + + +A records cause no additional section processing. The RDATA section of +an A line in a master file is an Internet address expressed as four +decimal numbers separated by dots without any embedded spaces (e.g., +"10.2.0.52" or "192.0.5.6"). + +3.4.2. WKS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PROTOCOL | | + +--+--+--+--+--+--+--+--+ | + | | + / <BIT MAP> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS An 32 bit Internet address + +PROTOCOL An 8 bit IP protocol number + +<BIT MAP> A variable length bit map. The bit map must be a + multiple of 8 bits long. + +The WKS record is used to describe the well known services supported by +a particular protocol on a particular internet address. The PROTOCOL +field specifies an IP protocol number, and the bit map has one bit per +port of the specified protocol. The first bit corresponds to port 0, +the second to port 1, etc. If the bit map does not include a bit for a +protocol of interest, that bit is assumed zero. The appropriate values +and mnemonics for ports and protocols are specified in [RFC-1010]. + +For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port +25 (SMTP). If this bit is set, a SMTP server should be listening on TCP +port 25; if zero, SMTP service is not supported on the specified +address. + +The purpose of WKS RRs is to provide availability information for +servers for TCP and UDP. If a server supports both TCP and UDP, or has +multiple Internet addresses, then multiple WKS RRs are used. + +WKS RRs cause no additional section processing. + +In master files, both ports and protocols are expressed using mnemonics +or decimal numbers. + + + + +Mockapetris [Page 21] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.5. IN-ADDR.ARPA domain + +The Internet uses a special domain to support gateway location and +Internet address to host mapping. Other classes may employ a similar +strategy in other domains. The intent of this domain is to provide a +guaranteed method to perform host address to host name mapping, and to +facilitate queries to locate all gateways on a particular network in the +Internet. + +Note that both of these services are similar to functions that could be +performed by inverse queries; the difference is that this part of the +domain name space is structured according to address, and hence can +guarantee that the appropriate data can be located without an exhaustive +search of the domain space. + +The domain begins at IN-ADDR.ARPA and has a substructure which follows +the Internet addressing structure. + +Domain names in the IN-ADDR.ARPA domain are defined to have up to four +labels in addition to the IN-ADDR.ARPA suffix. Each label represents +one octet of an Internet address, and is expressed as a character string +for a decimal value in the range 0-255 (with leading zeros omitted +except in the case of a zero octet which is represented by a single +zero). + +Host addresses are represented by domain names that have all four labels +specified. Thus data for Internet address 10.2.0.52 is located at +domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to +read, allows zones to be delegated which are exactly one network of +address space. For example, 10.IN-ADDR.ARPA can be a zone containing +data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for +MILNET. Address nodes are used to hold pointers to primary host names +in the normal domain space. + +Network numbers correspond to some non-terminal nodes at various depths +in the IN-ADDR.ARPA domain, since Internet network numbers are either 1, +2, or 3 octets. Network nodes are used to hold pointers to the primary +host names of gateways attached to that network. Since a gateway is, by +definition, on more than one network, it will typically have two or more +network nodes which point at it. Gateways will also have host level +pointers at their fully qualified addresses. + +Both the gateway pointers at network nodes and the normal host pointers +at full address nodes use the PTR RR to point back to the primary domain +names of the corresponding hosts. + +For example, the IN-ADDR.ARPA domain will contain information about the +ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's + + + +Mockapetris [Page 22] + +RFC 1035 Domain Implementation and Specification November 1987 + + +net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI +gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET- +GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4 +and a name GW.LCS.MIT.EDU, the domain database would contain: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU. + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Thus a program which wanted to locate gateways on net 10 would originate +a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It +would receive two RRs in response: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + +The program could then originate QTYPE=A, QCLASS=IN queries for MILNET- +GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of +these gateways. + +A resolver which wanted to find the host name corresponding to Internet +host address 10.0.0.6 would pursue a query of the form QTYPE=PTR, +QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive: + + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Several cautions apply to the use of these services: + - Since the IN-ADDR.ARPA special domain and the normal domain + for a particular host or gateway will be in different zones, + the possibility exists that that the data may be inconsistent. + + - Gateways will often have two names in separate domains, only + one of which can be primary. + + - Systems that use the domain database to initialize their + routing tables must start with enough gateway information to + guarantee that they can access the appropriate name server. + + - The gateway data only reflects the existence of a gateway in a + manner equivalent to the current HOSTS.TXT file. It doesn't + replace the dynamic availability information from GGP or EGP. + + + +Mockapetris [Page 23] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.6. Defining new types, classes, and special namespaces + +The previously defined types and classes are the ones in use as of the +date of this memo. New definitions should be expected. This section +makes some recommendations to designers considering additions to the +existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the +forum where general discussion of design issues takes place. + +In general, a new type is appropriate when new information is to be +added to the database about an existing object, or we need new data +formats for some totally new object. Designers should attempt to define +types and their RDATA formats that are generally applicable to all +classes, and which avoid duplication of information. New classes are +appropriate when the DNS is to be used for a new protocol, etc which +requires new class-specific data formats, or when a copy of the existing +name space is desired, but a separate management domain is necessary. + +New types and classes need mnemonics for master files; the format of the +master files requires that the mnemonics for type and class be disjoint. + +TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes +respectively. + +The present system uses multiple RRs to represent multiple values of a +type rather than storing multiple values in the RDATA section of a +single RR. This is less efficient for most applications, but does keep +RRs shorter. The multiple RRs assumption is incorporated in some +experimental work on dynamic update methods. + +The present system attempts to minimize the duplication of data in the +database in order to insure consistency. Thus, in order to find the +address of the host for a mail exchange, you map the mail domain name to +a host name, then the host name to addresses, rather than a direct +mapping to host address. This approach is preferred because it avoids +the opportunity for inconsistency. + +In defining a new type of data, multiple RR types should not be used to +create an ordering between entries or express different formats for +equivalent bindings, instead this information should be carried in the +body of the RR and a single type used. This policy avoids problems with +caching multiple types and defining QTYPEs to match multiple types. + +For example, the original form of mail exchange binding used two RR +types one to represent a "closer" exchange (MD) and one to represent a +"less close" exchange (MF). The difficulty is that the presence of one +RR type in a cache doesn't convey any information about the other +because the query which acquired the cached information might have used +a QTYPE of MF, MD, or MAILA (which matched both). The redesigned + + + +Mockapetris [Page 24] + +RFC 1035 Domain Implementation and Specification November 1987 + + +service used a single type (MX) with a "preference" value in the RDATA +section which can order different RRs. However, if any MX RRs are found +in the cache, then all should be there. + +4. MESSAGES + +4.1. Format + +All communications inside of the domain protocol are carried in a single +format called a message. The top level format of message is divided +into 5 sections (some of which are empty in certain cases) shown below: + + +---------------------+ + | Header | + +---------------------+ + | Question | the question for the name server + +---------------------+ + | Answer | RRs answering the question + +---------------------+ + | Authority | RRs pointing toward an authority + +---------------------+ + | Additional | RRs holding additional information + +---------------------+ + +The header section is always present. The header includes fields that +specify which of the remaining sections are present, and also specify +whether the message is a query or a response, a standard query or some +other opcode, etc. + +The names of the sections after the header are derived from their use in +standard queries. The question section contains fields that describe a +question to a name server. These fields are a query type (QTYPE), a +query class (QCLASS), and a query domain name (QNAME). The last three +sections have the same format: a possibly empty list of concatenated +resource records (RRs). The answer section contains RRs that answer the +question; the authority section contains RRs that point toward an +authoritative name server; the additional records section contains RRs +which relate to the query, but are not strictly answers for the +question. + + + + + + + + + + + + +Mockapetris [Page 25] + +RFC 1035 Domain Implementation and Specification November 1987 + + +4.1.1. Header section format + +The header contains the following fields: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ID A 16 bit identifier assigned by the program that + generates any kind of query. This identifier is copied + the corresponding reply and can be used by the requester + to match up replies to outstanding queries. + +QR A one bit field that specifies whether this message is a + query (0), or a response (1). + +OPCODE A four bit field that specifies kind of query in this + message. This value is set by the originator of a query + and copied into the response. The values are: + + 0 a standard query (QUERY) + + 1 an inverse query (IQUERY) + + 2 a server status request (STATUS) + + 3-15 reserved for future use + +AA Authoritative Answer - this bit is valid in responses, + and specifies that the responding name server is an + authority for the domain name in question section. + + Note that the contents of the answer section may have + multiple owner names because of aliases. The AA bit + + + +Mockapetris [Page 26] + +RFC 1035 Domain Implementation and Specification November 1987 + + + corresponds to the name which matches the query name, or + the first owner name in the answer section. + +TC TrunCation - specifies that this message was truncated + due to length greater than that permitted on the + transmission channel. + +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. + +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. + +Z Reserved for future use. Must be zero in all queries + and responses. + +RCODE Response code - this 4 bit field is set as part of + responses. The values have the following + interpretation: + + 0 No error condition + + 1 Format error - The name server was + unable to interpret the query. + + 2 Server failure - The name server was + unable to process this query due to a + problem with the name server. + + 3 Name Error - Meaningful only for + responses from an authoritative name + server, this code signifies that the + domain name referenced in the query does + not exist. + + 4 Not Implemented - The name server does + not support the requested kind of query. + + 5 Refused - The name server refuses to + perform the specified operation for + policy reasons. For example, a name + server may not wish to provide the + information to the particular requester, + or a name server may not wish to perform + a particular operation (e.g., zone + + + +Mockapetris [Page 27] + +RFC 1035 Domain Implementation and Specification November 1987 + + + transfer) for particular data. + + 6-15 Reserved for future use. + +QDCOUNT an unsigned 16 bit integer specifying the number of + entries in the question section. + +ANCOUNT an unsigned 16 bit integer specifying the number of + resource records in the answer section. + +NSCOUNT an unsigned 16 bit integer specifying the number of name + server resource records in the authority records + section. + +ARCOUNT an unsigned 16 bit integer specifying the number of + resource records in the additional records section. + +4.1.2. Question section format + +The question section is used to carry the "question" in most queries, +i.e., the parameters that define what is being asked. The section +contains QDCOUNT (usually 1) entries, each of the following format: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + +QTYPE a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR. + + + +Mockapetris [Page 28] + +RFC 1035 Domain Implementation and Specification November 1987 + + +QCLASS a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same +format: a variable number of resource records, where the number of +records is specified in the corresponding count field in the header. +Each resource record has the following format: + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NAME a domain name to which this resource record pertains. + +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA + field. + +CLASS two octets which specify the class of the data in the + RDATA field. + +TTL a 32 bit unsigned integer that specifies the time + interval (in seconds) that the resource record may be + cached before it should be discarded. Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached. + + + + + +Mockapetris [Page 29] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + For example, the if the TYPE is A and the CLASS is IN, + the RDATA field is a 4 octet ARPA Internet address. + +4.1.4. Message compression + +In order to reduce the size of messages, the domain system utilizes a +compression scheme which eliminates the repetition of domain names in a +message. In this scheme, an entire domain name or a list of labels at +the end of a domain name is replaced with a pointer to a prior occurrence +of the same name. + +The pointer takes the form of a two octet sequence: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. (The 10 and 01 combinations +are reserved for future use.) The OFFSET field specifies an offset from +the start of the message (i.e., the first octet of the ID field in the +domain header). A zero offset specifies the first byte of the ID field, +etc. + +The compression scheme allows a domain name in a message to be +represented as either: + + - a sequence of labels ending in a zero octet + + - a pointer + + - a sequence of labels ending with a pointer + +Pointers can only be used for occurrences of a domain name where the +format is not class specific. If this were not the case, a name server +or resolver would be required to know the format of all RRs it handled. +As yet, there are no such cases, but they may occur in future RDATA +formats. + +If a domain name is contained in a part of the message subject to a +length field (such as the RDATA section of an RR), and compression is + + + +Mockapetris [Page 30] + +RFC 1035 Domain Implementation and Specification November 1987 + + +used, the length of the compressed name is used in the length +calculation, rather than the length of the expanded name. + +Programs are free to avoid using pointers in messages they generate, +although this will reduce datagram capacity, and may cause truncation. +However all programs are required to understand arriving messages that +contain pointers. + +For example, a datagram might need to use the domain names F.ISI.ARPA, +FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the +message, these domain names might be represented as: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 20 | 1 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 22 | 3 | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 24 | S | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 26 | 4 | A | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 28 | R | P | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 30 | A | 0 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 40 | 3 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 42 | O | O | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 44 | 1 1| 20 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 64 | 1 1| 26 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 92 | 0 | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The domain name for F.ISI.ARPA is shown at offset 20. The domain name +FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to +concatenate a label for FOO to the previously defined F.ISI.ARPA. The +domain name ARPA is defined at offset 64 using a pointer to the ARPA +component of the name F.ISI.ARPA at 20; note that this pointer relies on +ARPA being the last label in the string at 20. The root domain name is + + + +Mockapetris [Page 31] + +RFC 1035 Domain Implementation and Specification November 1987 + + +defined by a single octet of zeros at 92; the root domain name has no +labels. + +4.2. Transport + +The DNS assumes that messages will be transmitted as datagrams or in a +byte stream carried by a virtual circuit. While virtual circuits can be +used for any DNS activity, datagrams are preferred for queries due to +their lower overhead and better performance. Zone refresh activities +must use virtual circuits because of the need for reliable transfer. + +The Internet supports name server access using TCP [RFC-793] on server +port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP +port 53 (decimal). + +4.2.1. UDP usage + +Messages sent using UDP user server port 53 (decimal). + +Messages carried by UDP are restricted to 512 bytes (not counting the IP +or UDP headers). Longer messages are truncated and the TC bit is set in +the header. + +UDP is not acceptable for zone transfers, but is the recommended method +for standard queries in the Internet. Queries sent using UDP may be +lost, and hence a retransmission strategy is required. Queries or their +responses may be reordered by the network, or by processing in name +servers, so resolvers should not depend on them being returned in order. + +The optimal UDP retransmission policy will vary with performance of the +Internet and the needs of the client, but the following are recommended: + + - The client should try other servers and server addresses + before repeating a query to a specific address of a server. + + - The retransmission interval should be based on prior + statistics if possible. Too aggressive retransmission can + easily slow responses for the community at large. Depending + on how well connected the client is to its expected servers, + the minimum retransmission interval should be 2-5 seconds. + +More suggestions on server selection and retransmission policy can be +found in the resolver section of this memo. + +4.2.2. TCP usage + +Messages sent over TCP connections use server port 53 (decimal). The +message is prefixed with a two byte length field which gives the message + + + +Mockapetris [Page 32] + +RFC 1035 Domain Implementation and Specification November 1987 + + +length, excluding the two byte length field. This length field allows +the low-level processing to assemble a complete message before beginning +to parse it. + +Several connection management policies are recommended: + + - The server should not block other activities waiting for TCP + data. + + - The server should support multiple connections. + + - The server should assume that the client will initiate + connection closing, and should delay closing its end of the + connection until all outstanding client requests have been + satisfied. + + - If the server needs to close a dormant connection to reclaim + resources, it should wait until the connection has been idle + for a period on the order of two minutes. In particular, the + server should allow the SOA and AXFR request sequence (which + begins a refresh operation) to be made on a single connection. + Since the server would be unable to answer queries anyway, a + unilateral close or reset may be used instead of a graceful + close. + +5. MASTER FILES + +Master files are text files that contain RRs in text form. Since the +contents of a zone can be expressed in the form of a list of RRs a +master file is most often used to define a zone, though it can be used +to list a cache's contents. Hence, this section first discusses the +format of RRs in a master file, and then the special considerations when +a master file is used to create a zone in some name server. + +5.1. Format + +The format of these files is a sequence of entries. Entries are +predominantly line-oriented, though parentheses can be used to continue +a list of items across a line boundary, and text literals can contain +CRLF within the text. Any combination of tabs and spaces act as a +delimiter between the separate items that make up an entry. The end of +any line in the master file can end with a comment. The comment starts +with a ";" (semicolon). + +The following entries are defined: + + <blank>[<comment>] + + + + +Mockapetris [Page 33] + +RFC 1035 Domain Implementation and Specification November 1987 + + + $ORIGIN <domain-name> [<comment>] + + $INCLUDE <file-name> [<domain-name>] [<comment>] + + <domain-name><rr> [<comment>] + + <blank><rr> [<comment>] + +Blank lines, with or without comments, are allowed anywhere in the file. + +Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is +followed by a domain name, and resets the current origin for relative +domain names to the stated name. $INCLUDE inserts the named file into +the current file, and may optionally specify a domain name that sets the +relative domain name origin for the included file. $INCLUDE may also +have a comment. Note that a $INCLUDE entry never changes the relative +origin of the parent file, regardless of changes to the relative origin +made within the included file. + +The last two forms represent RRs. If an entry for an RR begins with a +blank, then the RR is assumed to be owned by the last stated owner. If +an RR entry begins with a <domain-name>, then the owner name is reset. + +<rr> contents take one of the following forms: + + [<TTL>] [<class>] <type> <RDATA> + + [<class>] [<TTL>] <type> <RDATA> + +The RR begins with optional TTL and class fields, followed by a type and +RDATA field appropriate to the type and class. Class and type use the +standard mnemonics, TTL is a decimal integer. Omitted class and TTL +values are default to the last explicitly stated values. Since type and +class mnemonics are disjoint, the parse is unique. (Note that this +order is different from the order used in examples and the order used in +the actual RRs; the given order allows easier parsing and defaulting.) + +<domain-name>s make up a large share of the data in the master file. +The labels in the domain name are expressed as character strings and +separated by dots. Quoting conventions allow arbitrary characters to be +stored in domain names. Domain names that end in a dot are called +absolute, and are taken as complete. Domain names which do not end in a +dot are called relative; the actual domain name is the concatenation of +the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as +an argument to the master file loading routine. A relative name is an +error when no origin is available. + + + + + +Mockapetris [Page 34] + +RFC 1035 Domain Implementation and Specification November 1987 + + +<character-string> is expressed in one or two ways: as a contiguous set +of characters without interior spaces, or as a string beginning with a " +and ending with a ". Inside a " delimited string any character can +occur, except for a " itself, which must be quoted using \ (back slash). + +Because these files are text files several special encodings are +necessary to allow arbitrary data to be loaded. In particular: + + of the root. + +@ A free standing @ is used to denote the current origin. + +\X where X is any character other than a digit (0-9), is + used to quote that character so that its special meaning + does not apply. For example, "\." can be used to place + a dot character in a label. + +\DDD where each D is a digit is the octet corresponding to + the decimal number described by DDD. The resulting + octet is assumed to be text and is not checked for + special meaning. + +( ) Parentheses are used to group data that crosses a line + boundary. In effect, line terminations are not + recognized within parentheses. + +; Semicolon is used to start a comment; the remainder of + the line is ignored. + +5.2. Use of master files to define zones + +When a master file is used to load a zone, the operation should be +suppressed if any errors are encountered in the master file. The +rationale for this is that a single error can have widespread +consequences. For example, suppose that the RRs defining a delegation +have syntax errors; then the server will return authoritative name +errors for all names in the subzone (except in the case where the +subzone is also present on the server). + +Several other validity checks that should be performed in addition to +insuring that the file is syntactically correct: + + 1. All RRs in the file should have the same class. + + 2. Exactly one SOA RR should be present at the top of the zone. + + 3. If delegations are present and glue information is required, + it should be present. + + + +Mockapetris [Page 35] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 4. Information present outside of the authoritative nodes in the + zone should be glue information, rather than the result of an + origin or similar error. + +5.3. Master file example + +The following is an example file which might be used to define the +ISI.EDU zone.and is loaded with an origin of ISI.EDU: + +@ IN SOA VENERA Action\.domains ( + 20 ; SERIAL + 7200 ; REFRESH + 600 ; RETRY + 3600000; EXPIRE + 60) ; MINIMUM + + NS A.ISI.EDU. + NS VENERA + NS VAXA + MX 10 VENERA + MX 20 VAXA + +A A 26.3.0.103 + +VENERA A 10.1.0.52 + A 128.9.0.32 + +VAXA A 10.2.0.27 + A 128.9.0.33 + + +$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT + +Where the file <SUBSYS>ISI-MAILBOXES.TXT is: + + MOE MB A.ISI.EDU. + LARRY MB A.ISI.EDU. + CURLEY MB A.ISI.EDU. + STOOGES MG MOE + MG LARRY + MG CURLEY + +Note the use of the \ character in the SOA RR to specify the responsible +person mailbox "Action.domains@E.ISI.EDU". + + + + + + + +Mockapetris [Page 36] + +RFC 1035 Domain Implementation and Specification November 1987 + + +6. NAME SERVER IMPLEMENTATION + +6.1. Architecture + +The optimal structure for the name server will depend on the host +operating system and whether the name server is integrated with resolver +operations, either by supporting recursive service, or by sharing its +database with a resolver. This section discusses implementation +considerations for a name server which shares a database with a +resolver, but most of these concerns are present in any name server. + +6.1.1. Control + +A name server must employ multiple concurrent activities, whether they +are implemented as separate tasks in the host's OS or multiplexing +inside a single name server program. It is simply not acceptable for a +name server to block the service of UDP requests while it waits for TCP +data for refreshing or query activities. Similarly, a name server +should not attempt to provide recursive service without processing such +requests in parallel, though it may choose to serialize requests from a +single client, or to regard identical requests from the same client as +duplicates. A name server should not substantially delay requests while +it reloads a zone from master files or while it incorporates a newly +refreshed zone into its database. + +6.1.2. Database + +While name server implementations are free to use any internal data +structures they choose, the suggested structure consists of three major +parts: + + - A "catalog" data structure which lists the zones available to + this server, and a "pointer" to the zone data structure. The + main purpose of this structure is to find the nearest ancestor + zone, if any, for arriving standard queries. + + - Separate data structures for each of the zones held by the + name server. + + - A data structure for cached data. (or perhaps separate caches + for different classes) + +All of these data structures can be implemented an identical tree +structure format, with different data chained off the nodes in different +parts: in the catalog the data is pointers to zones, while in the zone +and cache data structures, the data will be RRs. In designing the tree +framework the designer should recognize that query processing will need +to traverse the tree using case-insensitive label comparisons; and that + + + +Mockapetris [Page 37] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in real data, a few nodes have a very high branching factor (100-1000 or +more), but the vast majority have a very low branching factor (0-1). + +One way to solve the case problem is to store the labels for each node +in two pieces: a standardized-case representation of the label where all +ASCII characters are in a single case, together with a bit mask that +denotes which characters are actually of a different case. The +branching factor diversity can be handled using a simple linked list for +a node until the branching factor exceeds some threshold, and +transitioning to a hash structure after the threshold is exceeded. In +any case, hash structures used to store tree sections must insure that +hash functions and procedures preserve the casing conventions of the +DNS. + +The use of separate structures for the different parts of the database +is motivated by several factors: + + - The catalog structure can be an almost static structure that + need change only when the system administrator changes the + zones supported by the server. This structure can also be + used to store parameters used to control refreshing + activities. + + - The individual data structures for zones allow a zone to be + replaced simply by changing a pointer in the catalog. Zone + refresh operations can build a new structure and, when + complete, splice it into the database via a simple pointer + replacement. It is very important that when a zone is + refreshed, queries should not use old and new data + simultaneously. + + - With the proper search procedures, authoritative data in zones + will always "hide", and hence take precedence over, cached + data. + + - Errors in zone definitions that cause overlapping zones, etc., + may cause erroneous responses to queries, but problem + determination is simplified, and the contents of one "bad" + zone can't corrupt another. + + - Since the cache is most frequently updated, it is most + vulnerable to corruption during system restarts. It can also + become full of expired RR data. In either case, it can easily + be discarded without disturbing zone data. + +A major aspect of database design is selecting a structure which allows +the name server to deal with crashes of the name server's host. State +information which a name server should save across system crashes + + + +Mockapetris [Page 38] + +RFC 1035 Domain Implementation and Specification November 1987 + + +includes the catalog structure (including the state of refreshing for +each zone) and the zone data itself. + +6.1.3. Time + +Both the TTL data for RRs and the timing data for refreshing activities +depends on 32 bit timers in units of seconds. Inside the database, +refresh timers and TTLs for cached data conceptually "count down", while +data in the zone stays with constant TTLs. + +A recommended implementation strategy is to store time in two ways: as +a relative increment and as an absolute time. One way to do this is to +use positive 32 bit numbers for one type and negative numbers for the +other. The RRs in zones use relative times; the refresh timers and +cache data use absolute times. Absolute numbers are taken with respect +to some known origin and converted to relative values when placed in the +response to a query. When an absolute TTL is negative after conversion +to relative, then the data is expired and should be ignored. + +6.2. Standard query processing + +The major algorithm for standard query processing is presented in +[RFC-1034]. + +When processing queries with QCLASS=*, or some other QCLASS which +matches multiple classes, the response should never be authoritative +unless the server can guarantee that the response covers all classes. + +When composing a response, RRs which are to be inserted in the +additional section, but duplicate RRs in the answer or authority +sections, may be omitted from the additional section. + +When a response is so long that truncation is required, the truncation +should start at the end of the response and work forward in the +datagram. Thus if there is any data for the authority section, the +answer section is guaranteed to be unique. + +The MINIMUM value in the SOA should be used to set a floor on the TTL of +data distributed from a zone. This floor function should be done when +the data is copied into a response. This will allow future dynamic +update protocols to change the SOA MINIMUM field without ambiguous +semantics. + +6.3. Zone refresh and reload processing + +In spite of a server's best efforts, it may be unable to load zone data +from a master file due to syntax errors, etc., or be unable to refresh a +zone within the its expiration parameter. In this case, the name server + + + +Mockapetris [Page 39] + +RFC 1035 Domain Implementation and Specification November 1987 + + +should answer queries as if it were not supposed to possess the zone. + +If a master is sending a zone out via AXFR, and a new version is created +during the transfer, the master should continue to send the old version +if possible. In any case, it should never send part of one version and +part of another. If completion is not possible, the master should reset +the connection on which the zone transfer is taking place. + +6.4. Inverse queries (Optional) + +Inverse queries are an optional part of the DNS. Name servers are not +required to support any form of inverse queries. If a name server +receives an inverse query that it does not support, it returns an error +response with the "Not Implemented" error set in the header. While +inverse query support is optional, all name servers must be at least +able to return the error response. + +6.4.1. The contents of inverse queries and responses Inverse +queries reverse the mappings performed by standard query operations; +while a standard query maps a domain name to a resource, an inverse +query maps a resource to a domain name. For example, a standard query +might bind a domain name to a host address; the corresponding inverse +query binds the host address to a domain name. + +Inverse queries take the form of a single RR in the answer section of +the message, with an empty question section. The owner name of the +query RR and its TTL are not significant. The response carries +questions in the question section which identify all names possessing +the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows +about all of the domain name space, the response can never be assumed to +be complete. Thus inverse queries are primarily useful for database +management and debugging activities. Inverse queries are NOT an +acceptable method of mapping host addresses to host names; use the IN- +ADDR.ARPA domain instead. + +Where possible, name servers should provide case-insensitive comparisons +for inverse queries. Thus an inverse query asking for an MX RR of +"Venera.isi.edu" should get the same response as a query for +"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should +produce the same result as an inverse query for "IBM-pc unix". However, +this cannot be guaranteed because name servers may possess RRs that +contain character strings but the name server does not know that the +data is character. + +When a name server processes an inverse query, it either returns: + + 1. zero, one, or multiple domain names for the specified + resource as QNAMEs in the question section + + + +Mockapetris [Page 40] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 2. an error code indicating that the name server doesn't support + inverse mapping of the specified resource type. + +When the response to an inverse query contains one or more QNAMEs, the +owner name and TTL of the RR in the answer section which defines the +inverse query is modified to exactly match an RR found at the first +QNAME. + +RRs returned in the inverse queries cannot be cached using the same +mechanism as is used for the replies to standard queries. One reason +for this is that a name might have multiple RRs of the same type, and +only one would appear. For example, an inverse query for a single +address of a multiply homed host might create the impression that only +one address existed. + +6.4.2. Inverse query and response example The overall structure +of an inverse query for retrieving the domain name that corresponds to +Internet address 10.1.0.52 is shown below: + + +-----------------------------------------+ + Header | OPCODE=IQUERY, ID=997 | + +-----------------------------------------+ + Question | <empty> | + +-----------------------------------------+ + Answer | <anyname> A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +This query asks for a question whose answer is the Internet style +address 10.1.0.52. Since the owner name is not known, any domain name +can be used as a placeholder (and is ignored). A single octet of zero, +signifying the root, is usually used because it minimizes the length of +the message. The TTL of the RR is not significant. The response to +this query might be: + + + + + + + + + + + + + + +Mockapetris [Page 41] + +RFC 1035 Domain Implementation and Specification November 1987 + + + +-----------------------------------------+ + Header | OPCODE=RESPONSE, ID=997 | + +-----------------------------------------+ + Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU | + +-----------------------------------------+ + Answer | VENERA.ISI.EDU A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +Note that the QTYPE in a response to an inverse query is the same as the +TYPE field in the answer section of the inverse query. Responses to +inverse queries may contain multiple questions when the inverse is not +unique. If the question section in the response is not empty, then the +RR in the answer section is modified to correspond to be an exact copy +of an RR at the first QNAME. + +6.4.3. Inverse query processing + +Name servers that support inverse queries can support these operations +through exhaustive searches of their databases, but this becomes +impractical as the size of the database increases. An alternative +approach is to invert the database according to the search key. + +For name servers that support multiple zones and a large amount of data, +the recommended approach is separate inversions for each zone. When a +particular zone is changed during a refresh, only its inversions need to +be redone. + +Support for transfer of this type of inversion may be included in future +versions of the domain system, but is not supported in this version. + +6.5. Completion queries and responses + +The optional completion services described in RFC-882 and RFC-883 have +been deleted. Redesigned services may become available in the future. + + + + + + + + + + + + + +Mockapetris [Page 42] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7. RESOLVER IMPLEMENTATION + +The top levels of the recommended resolver algorithm are discussed in +[RFC-1034]. This section discusses implementation details assuming the +database structure suggested in the name server implementation section +of this memo. + +7.1. Transforming a user request into a query + +The first step a resolver takes is to transform the client's request, +stated in a format suitable to the local OS, into a search specification +for RRs at a specific name which match a specific QTYPE and QCLASS. +Where possible, the QTYPE and QCLASS should correspond to a single type +and a single class, because this makes the use of cached data much +simpler. The reason for this is that the presence of data of one type +in a cache doesn't confirm the existence or non-existence of data of +other types, hence the only way to be sure is to consult an +authoritative source. If QCLASS=* is used, then authoritative answers +won't be available. + +Since a resolver must be able to multiplex multiple requests if it is to +perform its function efficiently, each pending request is usually +represented in some block of state information. This state block will +typically contain: + + - A timestamp indicating the time the request began. + The timestamp is used to decide whether RRs in the database + can be used or are out of date. This timestamp uses the + absolute time format previously discussed for RR storage in + zones and caches. Note that when an RRs TTL indicates a + relative time, the RR must be timely, since it is part of a + zone. When the RR has an absolute time, it is part of a + cache, and the TTL of the RR is compared against the timestamp + for the start of the request. + + Note that using the timestamp is superior to using a current + time, since it allows RRs with TTLs of zero to be entered in + the cache in the usual manner, but still used by the current + request, even after intervals of many seconds due to system + load, query retransmission timeouts, etc. + + - Some sort of parameters to limit the amount of work which will + be performed for this request. + + The amount of work which a resolver will do in response to a + client request must be limited to guard against errors in the + database, such as circular CNAME references, and operational + problems, such as network partition which prevents the + + + +Mockapetris [Page 43] + +RFC 1035 Domain Implementation and Specification November 1987 + + + resolver from accessing the name servers it needs. While + local limits on the number of times a resolver will retransmit + a particular query to a particular name server address are + essential, the resolver should have a global per-request + counter to limit work on a single request. The counter should + be set to some initial value and decremented whenever the + resolver performs any action (retransmission timeout, + retransmission, etc.) If the counter passes zero, the request + is terminated with a temporary error. + + Note that if the resolver structure allows one request to + start others in parallel, such as when the need to access a + name server for one request causes a parallel resolve for the + name server's addresses, the spawned request should be started + with a lower counter. This prevents circular references in + the database from starting a chain reaction of resolver + activity. + + - The SLIST data structure discussed in [RFC-1034]. + + This structure keeps track of the state of a request if it + must wait for answers from foreign name servers. + +7.2. Sending the queries + +As described in [RFC-1034], the basic task of the resolver is to +formulate a query which will answer the client's request and direct that +query to name servers which can provide the information. The resolver +will usually only have very strong hints about which servers to ask, in +the form of NS RRs, and may have to revise the query, in response to +CNAMEs, or revise the set of name servers the resolver is asking, in +response to delegation responses which point the resolver to name +servers closer to the desired information. In addition to the +information requested by the client, the resolver may have to call upon +its own services to determine the address of name servers it wishes to +contact. + +In any case, the model used in this memo assumes that the resolver is +multiplexing attention between multiple requests, some from the client, +and some internally generated. Each request is represented by some +state information, and the desired behavior is that the resolver +transmit queries to name servers in a way that maximizes the probability +that the request is answered, minimizes the time that the request takes, +and avoids excessive transmissions. The key algorithm uses the state +information of the request to select the next name server address to +query, and also computes a timeout which will cause the next action +should a response not arrive. The next action will usually be a +transmission to some other server, but may be a temporary error to the + + + +Mockapetris [Page 44] + +RFC 1035 Domain Implementation and Specification November 1987 + + +client. + +The resolver always starts with a list of server names to query (SLIST). +This list will be all NS RRs which correspond to the nearest ancestor +zone that the resolver knows about. To avoid startup problems, the +resolver should have a set of default servers which it will ask should +it have no current NS RRs which are appropriate. The resolver then adds +to SLIST all of the known addresses for the name servers, and may start +parallel requests to acquire the addresses of the servers when the +resolver has the name, but no addresses, for the name servers. + +To complete initialization of SLIST, the resolver attaches whatever +history information it has to the each address in SLIST. This will +usually consist of some sort of weighted averages for the response time +of the address, and the batting average of the address (i.e., how often +the address responded at all to the request). Note that this +information should be kept on a per address basis, rather than on a per +name server basis, because the response time and batting average of a +particular server may vary considerably from address to address. Note +also that this information is actually specific to a resolver address / +server address pair, so a resolver with multiple addresses may wish to +keep separate histories for each of its addresses. Part of this step +must deal with addresses which have no such history; in this case an +expected round trip time of 5-10 seconds should be the worst case, with +lower estimates for the same local network, etc. + +Note that whenever a delegation is followed, the resolver algorithm +reinitializes SLIST. + +The information establishes a partial ranking of the available name +server addresses. Each time an address is chosen and the state should +be altered to prevent its selection again until all other addresses have +been tried. The timeout for each transmission should be 50-100% greater +than the average predicted value to allow for variance in response. + +Some fine points: + + - The resolver may encounter a situation where no addresses are + available for any of the name servers named in SLIST, and + where the servers in the list are precisely those which would + normally be used to look up their own addresses. This + situation typically occurs when the glue address RRs have a + smaller TTL than the NS RRs marking delegation, or when the + resolver caches the result of a NS search. The resolver + should detect this condition and restart the search at the + next ancestor zone, or alternatively at the root. + + + + + +Mockapetris [Page 45] + +RFC 1035 Domain Implementation and Specification November 1987 + + + - If a resolver gets a server error or other bizarre response + from a name server, it should remove it from SLIST, and may + wish to schedule an immediate transmission to the next + candidate server address. + +7.3. Processing responses + +The first step in processing arriving response datagrams is to parse the +response. This procedure should include: + + - Check the header for reasonableness. Discard datagrams which + are queries when responses are expected. + + - Parse the sections of the message, and insure that all RRs are + correctly formatted. + + - As an optional step, check the TTLs of arriving data looking + for RRs with excessively long TTLs. If a RR has an + excessively long TTL, say greater than 1 week, either discard + the whole response, or limit all TTLs in the response to 1 + week. + +The next step is to match the response to a current resolver request. +The recommended strategy is to do a preliminary matching using the ID +field in the domain header, and then to verify that the question section +corresponds to the information currently desired. This requires that +the transmission algorithm devote several bits of the domain ID field to +a request identifier of some sort. This step has several fine points: + + - Some name servers send their responses from different + addresses than the one used to receive the query. That is, a + resolver cannot rely that a response will come from the same + address which it sent the corresponding query to. This name + server bug is typically encountered in UNIX systems. + + - If the resolver retransmits a particular request to a name + server it should be able to use a response from any of the + transmissions. However, if it is using the response to sample + the round trip time to access the name server, it must be able + to determine which transmission matches the response (and keep + transmission times for each outgoing message), or only + calculate round trip times based on initial transmissions. + + - A name server will occasionally not have a current copy of a + zone which it should have according to some NS RRs. The + resolver should simply remove the name server from the current + SLIST, and continue. + + + + +Mockapetris [Page 46] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7.4. Using the cache + +In general, we expect a resolver to cache all data which it receives in +responses since it may be useful in answering future client requests. +However, there are several types of data which should not be cached: + + - When several RRs of the same type are available for a + particular owner name, the resolver should either cache them + all or none at all. When a response is truncated, and a + resolver doesn't know whether it has a complete set, it should + not cache a possibly partial set of RRs. + + - Cached data should never be used in preference to + authoritative data, so if caching would cause this to happen + the data should not be cached. + + - The results of an inverse query should not be cached. + + - The results of standard queries where the QNAME contains "*" + labels if the data might be used to construct wildcards. The + reason is that the cache does not necessarily contain existing + RRs or zone boundary information which is necessary to + restrict the application of the wildcard RRs. + + - RR data in responses of dubious reliability. When a resolver + receives unsolicited responses or RR data other than that + requested, it should discard it without caching it. The basic + implication is that all sanity checks on a packet should be + performed before any of it is cached. + +In a similar vein, when a resolver has a set of RRs for some name in a +response, and wants to cache the RRs, it should check its cache for +already existing RRs. Depending on the circumstances, either the data +in the response or the cache is preferred, but the two should never be +combined. If the data in the response is from authoritative data in the +answer section, it is always preferred. + +8. MAIL SUPPORT + +The domain system defines a standard for mapping mailboxes into domain +names, and two methods for using the mailbox information to derive mail +routing information. The first method is called mail exchange binding +and the other method is mailbox binding. The mailbox encoding standard +and mail exchange binding are part of the DNS official protocol, and are +the recommended method for mail routing in the Internet. Mailbox +binding is an experimental feature which is still under development and +subject to change. + + + + +Mockapetris [Page 47] + +RFC 1035 Domain Implementation and Specification November 1987 + + +The mailbox encoding standard assumes a mailbox name of the form +"<local-part>@<mail-domain>". While the syntax allowed in each of these +sections varies substantially between the various mail internets, the +preferred syntax for the ARPA Internet is given in [RFC-822]. + +The DNS encodes the <local-part> as a single label, and encodes the +<mail-domain> as a domain name. The single label from the <local-part> +is prefaced to the domain name from <mail-domain> to form the domain +name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI- +NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the +<local-part> contains dots or other special characters, its +representation in a master file will require the use of backslash +quoting to ensure that the domain name is properly encoded. For +example, the mailbox Action.domains@ISI.EDU would be represented as +Action\.domains.ISI.EDU. + +8.1. Mail exchange binding + +Mail exchange binding uses the <mail-domain> part of a mailbox +specification to determine where mail should be sent. The <local-part> +is not even consulted. [RFC-974] specifies this method in detail, and +should be consulted before attempting to use mail exchange support. + +One of the advantages of this method is that it decouples mail +destination naming from the hosts used to support mail service, at the +cost of another layer of indirection in the lookup function. However, +the addition layer should eliminate the need for complicated "%", "!", +etc encodings in <local-part>. + +The essence of the method is that the <mail-domain> is used as a domain +name to locate type MX RRs which list hosts willing to accept mail for +<mail-domain>, together with preference values which rank the hosts +according to an order specified by the administrators for <mail-domain>. + +In this memo, the <mail-domain> ISI.EDU is used in examples, together +with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for +ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would +route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name +VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host +addresses. + +8.2. Mailbox binding (Experimental) + +In mailbox binding, the mailer uses the entire mail destination +specification to construct a domain name. The encoded domain name for +the mailbox is used as the QNAME field in a QTYPE=MAILB query. + +Several outcomes are possible for this query: + + + +Mockapetris [Page 48] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 1. The query can return a name error indicating that the mailbox + does not exist as a domain name. + + In the long term, this would indicate that the specified + mailbox doesn't exist. However, until the use of mailbox + binding is universal, this error condition should be + interpreted to mean that the organization identified by the + global part does not support mailbox binding. The + appropriate procedure is to revert to exchange binding at + this point. + + 2. The query can return a Mail Rename (MR) RR. + + The MR RR carries new mailbox specification in its RDATA + field. The mailer should replace the old mailbox with the + new one and retry the operation. + + 3. The query can return a MB RR. + + The MB RR carries a domain name for a host in its RDATA + field. The mailer should deliver the message to that host + via whatever protocol is applicable, e.g., b,SMTP. + + 4. The query can return one or more Mail Group (MG) RRs. + + This condition means that the mailbox was actually a mailing + list or mail group, rather than a single mailbox. Each MG RR + has a RDATA field that identifies a mailbox that is a member + of the group. The mailer should deliver a copy of the + message to each member. + + 5. The query can return a MB RR as well as one or more MG RRs. + + This condition means the the mailbox was actually a mailing + list. The mailer can either deliver the message to the host + specified by the MB RR, which will in turn do the delivery to + all members, or the mailer can use the MG RRs to do the + expansion itself. + +In any of these cases, the response may include a Mail Information +(MINFO) RR. This RR is usually associated with a mail group, but is +legal with a MB. The MINFO RR identifies two mailboxes. One of these +identifies a responsible person for the original mailbox name. This +mailbox should be used for requests to be added to a mail group, etc. +The second mailbox name in the MINFO RR identifies a mailbox that should +receive error messages for mail failures. This is particularly +appropriate for mailing lists when errors in member names should be +reported to a person other than the one who sends a message to the list. + + + +Mockapetris [Page 49] + +RFC 1035 Domain Implementation and Specification November 1987 + + +New fields may be added to this RR in the future. + + +9. REFERENCES and BIBLIOGRAPHY + +[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena + Technical Plan - Name Service, April 1987, version 1.9. + + Describes the fundamentals of the Hesiod name service. + +[IEN-116] J. Postel, "Internet Name Server", IEN-116, + USC/Information Sciences Institute, August 1979. + + A name service obsoleted by the Domain Name System, but + still in use. + +[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks", + Communications of the ACM, October 1986, volume 29, number + 10. + +[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network + Information Center, SRI International, December 1977. + +[RFC-768] J. Postel, "User Datagram Protocol", RFC-768, + USC/Information Sciences Institute, August 1980. + +[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793, + USC/Information Sciences Institute, September 1981. + +[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT, + September 1981. + + Suggests introduction of a hierarchy in place of a flat + name space for the Internet. + +[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805, + USC/Information Sciences Institute, February 1982. + +[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD + Internet Host Table Specification", RFC-810, Network + Information Center, SRI International, March 1982. + + Obsolete. See RFC-952. + +[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames + Server", RFC-811, Network Information Center, SRI + International, March 1982. + + + + +Mockapetris [Page 50] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Obsolete. See RFC-953. + +[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812, + Network Information Center, SRI International, March + 1982. + +[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for + Internet User Applications", RFC-819, Network + Information Center, SRI International, August 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821, + USC/Information Sciences Institute, August 1980. + +[RFC-830] Z. Su, "A Distributed System for Internet Name Service", + RFC-830, Network Information Center, SRI International, + October 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-882] P. Mockapetris, "Domain names - Concepts and + Facilities," RFC-882, USC/Information Sciences + Institute, November 1983. + + Superseded by this memo. + +[RFC-883] P. Mockapetris, "Domain names - Implementation and + Specification," RFC-883, USC/Information Sciences + Institute, November 1983. + + Superseded by this memo. + +[RFC-920] J. Postel and J. Reynolds, "Domain Requirements", + RFC-920, USC/Information Sciences Institute, + October 1984. + + Explains the naming scheme for top level domains. + +[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host + Table Specification", RFC-952, SRI, October 1985. + + Specifies the format of HOSTS.TXT, the host/address + table replaced by the DNS. + + + + + +Mockapetris [Page 51] + +RFC 1035 Domain Implementation and Specification November 1987 + + +[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server", + RFC-953, SRI, October 1985. + + This RFC contains the official specification of the + hostname server protocol, which is obsoleted by the DNS. + This TCP based protocol accesses information stored in + the RFC-952 format, and is used to obtain copies of the + host table. + +[RFC-973] P. Mockapetris, "Domain System Changes and + Observations", RFC-973, USC/Information Sciences + Institute, January 1986. + + Describes changes to RFC-882 and RFC-883 and reasons for + them. + +[RFC-974] C. Partridge, "Mail routing and the domain system", + RFC-974, CSNET CIC BBN Labs, January 1986. + + Describes the transition from HOSTS.TXT based mail + addressing to the more powerful MX system used with the + domain system. + +[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Concepts and Methods", + RFC-1001, March 1987. + + This RFC and RFC-1002 are a preliminary design for + NETBIOS on top of TCP/IP which proposes to base NetBIOS + name service on top of the DNS. + +[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Detailed + Specifications", RFC-1002, March 1987. + +[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010, + USC/Information Sciences Institute, May 1987. + + Contains socket numbers and mnemonics for host names, + operating systems, etc. + +[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031, + November 1987. + + Describes a plan for converting the MILNET to the DNS. + +[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for + Administrators", RFC-1032, November 1987. + + + +Mockapetris [Page 52] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Describes the registration policies used by the NIC to + administer the top level domains and delegate subzones. + +[RFC-1033] M. Lottor, "Domain Administrators Operations Guide", + RFC-1033, November 1987. + + A cookbook for domain administrators. + +[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET + Name Server", Computer Networks, vol 6, nr 3, July 1982. + + Describes a name service for CSNET which is independent + from the DNS and DNS use in the CSNET. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 53] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Index + + * 13 + + ; 33, 35 + + <character-string> 35 + <domain-name> 34 + + @ 35 + + \ 35 + + A 12 + + Byte order 8 + + CH 13 + Character case 9 + CLASS 11 + CNAME 12 + Completion 42 + CS 13 + + Hesiod 13 + HINFO 12 + HS 13 + + IN 13 + IN-ADDR.ARPA domain 22 + Inverse queries 40 + + Mailbox names 47 + MB 12 + MD 12 + MF 12 + MG 12 + MINFO 12 + MINIMUM 20 + MR 12 + MX 12 + + NS 12 + NULL 12 + + Port numbers 32 + Primary server 5 + PTR 12, 18 + + + +Mockapetris [Page 54] + +RFC 1035 Domain Implementation and Specification November 1987 + + + QCLASS 13 + QTYPE 12 + + RDATA 12 + RDLENGTH 11 + + Secondary server 5 + SOA 12 + Stub resolvers 7 + + TCP 32 + TXT 12 + TYPE 11 + + UDP 32 + + WKS 12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 55] + diff --git a/tests/dns/testdata/dst/test1.ecdsa256sig b/tests/dns/testdata/dst/test1.ecdsa256sig new file mode 100644 index 0000000..dcae9d1 --- /dev/null +++ b/tests/dns/testdata/dst/test1.ecdsa256sig @@ -0,0 +1 @@ +72E0998732EECAE2BEA12A278DFDEE14DB09A43C1E646A08BB0A6EEB90C5B75F9B359BEC1580313BFA8012C1DC15D34D1B227C71AD23161E2757AEB162AE3D99 diff --git a/tests/dns/testdata/dst/test1.rsasha256sig b/tests/dns/testdata/dst/test1.rsasha256sig new file mode 100644 index 0000000..36e0b09 --- /dev/null +++ b/tests/dns/testdata/dst/test1.rsasha256sig @@ -0,0 +1 @@ +C5CC8AB9FB5C0B4F03650456C993A868EB674ACBF2A867E023DC00F17D240CEDCADB8714981B7B48CF6CF86722632610FF312063B5E6D20EF441B89F02BC6813A35F9C6F045D017DB75C8724DBAA0C55A0D4EA850339944C75890B4DD0382AFA3E30E1CAA7B190C1B1FB17B5DD2279C0DF1049911E64198B3376070A34F38F4B diff --git a/tests/dns/testdata/dst/test2.data b/tests/dns/testdata/dst/test2.data new file mode 100644 index 0000000..a323bb3 --- /dev/null +++ b/tests/dns/testdata/dst/test2.data @@ -0,0 +1,3077 @@ +Network Working Group P. Mockapetris +Request for Comments: 1035 ISI + November 1987 +Obsoletes: RFCs 882, 883, 973 + + DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION + + +1. STATUS OF THIS MEMO + +This RFC describes the details of the domain system and protocol, and +assumes that the reader is familiar with the concepts discussed in a +companion RFC, "Domain Names - Concepts and Facilities" [RFC-4301]. + +The domain system is a mixture of functions and data types which are an +official protocol and functions and data types which are still +experimental. Since the domain system is intentionally extensible, new +data types and experimental behavior should always be expected in parts +of the system beyond the official protocol. The official protocol parts +include standard queries, responses and the Internet class RR data +formats (e.g., host addresses). Since the previous RFC set, several +definitions have changed, so some previous definitions are obsolete. + +Experimental or obsolete features are clearly marked in these RFCs, and +such information should be used with caution. + +The reader is especially cautioned not to depend on the values which +appear in examples to be current or complete, since their purpose is +primarily pedagogical. Distribution of this memo is unlimited. + + Table of Contents + + 1. STATUS OF THIS MEMO 1 + 2. INTRODUCTION 3 + 2.1. Overview 3 + 2.2. Common configurations 4 + 2.3. Conventions 7 + 2.3.1. Preferred name syntax 7 + 2.3.2. Data Transmission Order 8 + 2.3.3. Character Case 9 + 2.3.4. Size limits 10 + 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 + 3.1. Name space definitions 10 + 3.2. RR definitions 11 + 3.2.1. Format 11 + 3.2.2. TYPE values 12 + 3.2.3. QTYPE values 12 + 3.2.4. CLASS values 13 + + + +Mockapetris [Page 1] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 3.2.5. QCLASS values 13 + 3.3. Standard RRs 13 + 3.3.1. CNAME RDATA format 14 + 3.3.2. HINFO RDATA format 14 + 3.3.3. MB RDATA format (EXPERIMENTAL) 14 + 3.3.4. MD RDATA format (Obsolete) 15 + 3.3.5. MF RDATA format (Obsolete) 15 + 3.3.6. MG RDATA format (EXPERIMENTAL) 16 + 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 + 3.3.8. MR RDATA format (EXPERIMENTAL) 17 + 3.3.9. MX RDATA format 17 + 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 + 3.3.11. NS RDATA format 18 + 3.3.12. PTR RDATA format 18 + 3.3.13. SOA RDATA format 19 + 3.3.14. TXT RDATA format 20 + 3.4. ARPA Internet specific RRs 20 + 3.4.1. A RDATA format 20 + 3.4.2. WKS RDATA format 21 + 3.5. IN-ADDR.ARPA domain 22 + 3.6. Defining new types, classes, and special namespaces 24 + 4. MESSAGES 25 + 4.1. Format 25 + 4.1.1. Header section format 26 + 4.1.2. Question section format 28 + 4.1.3. Resource record format 29 + 4.1.4. Message compression 30 + 4.2. Transport 32 + 4.2.1. UDP usage 32 + 4.2.2. TCP usage 32 + 5. MASTER FILES 33 + 5.1. Format 33 + 5.2. Use of master files to define zones 35 + 5.3. Master file example 36 + 6. NAME SERVER IMPLEMENTATION 37 + 6.1. Architecture 37 + 6.1.1. Control 37 + 6.1.2. Database 37 + 6.1.3. Time 39 + 6.2. Standard query processing 39 + 6.3. Zone refresh and reload processing 39 + 6.4. Inverse queries (Optional) 40 + 6.4.1. The contents of inverse queries and responses 40 + 6.4.2. Inverse query and response example 41 + 6.4.3. Inverse query processing 42 + + + + + + +Mockapetris [Page 2] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 6.5. Completion queries and responses 42 + 7. RESOLVER IMPLEMENTATION 43 + 7.1. Transforming a user request into a query 43 + 7.2. Sending the queries 44 + 7.3. Processing responses 46 + 7.4. Using the cache 47 + 8. MAIL SUPPORT 47 + 8.1. Mail exchange binding 48 + 8.2. Mailbox binding (Experimental) 48 + 9. REFERENCES and BIBLIOGRAPHY 50 + Index 54 + +2. INTRODUCTION + +2.1. Overview + +The goal of domain names is to provide a mechanism for naming resources +in such a way that the names are usable in different hosts, networks, +protocol families, internets, and administrative organizations. + +From the user's point of view, domain names are useful as arguments to a +local agent, called a resolver, which retrieves information associated +with the domain name. Thus a user might ask for the host address or +mail information associated with a particular domain name. To enable +the user to request a particular type of information, an appropriate +query type is passed to the resolver with the domain name. To the user, +the domain tree is a single information space; the resolver is +responsible for hiding the distribution of data among name servers from +the user. + +From the resolver's point of view, the database that makes up the domain +space is distributed among various name servers. Different parts of the +domain space are stored in different name servers, although a particular +data item will be stored redundantly in two or more name servers. The +resolver starts with knowledge of at least one name server. When the +resolver processes a user query it asks a known name server for the +information; in return, the resolver either receives the desired +information or a referral to another name server. Using these +referrals, resolvers learn the identities and contents of other name +servers. Resolvers are responsible for dealing with the distribution of +the domain space and dealing with the effects of name server failure by +consulting redundant databases in other servers. + +Name servers manage two kinds of data. The first kind of data held in +sets called zones; each zone is the complete database for a particular +"pruned" subtree of the domain space. This data is called +authoritative. A name server periodically checks to make sure that its +zones are up to date, and if not, obtains a new copy of updated zones + + + +Mockapetris [Page 3] + +RFC 1035 Domain Implementation and Specification November 1987 + + +from master files stored locally or in another name server. The second +kind of data is cached data which was acquired by a local resolver. +This data may be incomplete, but improves the performance of the +retrieval process when non-local data is repeatedly accessed. Cached +data is eventually discarded by a timeout mechanism. + +This functional structure isolates the problems of user interface, +failure recovery, and distribution in the resolvers and isolates the +database update and refresh problems in the name servers. + +2.2. Common configurations + +A host can participate in the domain name system in a number of ways, +depending on whether the host runs programs that retrieve information +from the domain system, name servers that answer queries from other +hosts, or various combinations of both functions. The simplest, and +perhaps most typical, configuration is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | cache | | + +----------+ | + +User programs interact with the domain name space through resolvers; the +format of user queries and user responses is specific to the host and +its operating system. User queries will typically be operating system +calls, and the resolver and its cache will be part of the host operating +system. Less capable hosts may choose to implement the resolver as a +subroutine to be linked in with every program that needs its services. +Resolvers answer user queries with information they acquire via queries +to foreign name servers and the local cache. + +Note that the resolver may have to make several queries to several +different foreign name servers to answer a particular user query, and +hence the resolution of a user query may involve several network +accesses and an arbitrary amount of time. The queries to foreign name +servers and the corresponding responses have a standard format described + + + +Mockapetris [Page 4] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in this memo, and may be datagrams. + +Depending on its capabilities, a name server could be a stand alone +program on a dedicated machine or a process or processes on a large +timeshared host. A simple configuration might be: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + +Here a primary name server acquires information about one or more zones +by reading master files from its local file system, and answers queries +about those zones that arrive from foreign resolvers. + +The DNS requires that all zones be redundantly supported by more than +one name server. Designated secondary servers can acquire zones and +check for updates from the primary server using the zone transfer +protocol of the DNS. This configuration is shown below: + + Local Host | Foreign + | + +---------+ | + / /| | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +In this configuration, the name server periodically establishes a +virtual circuit to a foreign name server to acquire a copy of a zone or +to check that an existing copy has not changed. The messages sent for + + + +Mockapetris [Page 5] + +RFC 1035 Domain Implementation and Specification November 1987 + + +these maintenance activities follow the same form as queries and +responses, but the message sequences are somewhat different. + +The information flow in a host that supports all aspects of the domain +name system is shown below: + + Local Host | Foreign + | + +---------+ +----------+ | +--------+ + | | user queries | |queries | | | + | User |-------------->| |---------|->|Foreign | + | Program | | Resolver | | | Name | + | |<--------------| |<--------|--| Server | + | | user responses| |responses| | | + +---------+ +----------+ | +--------+ + | A | + cache additions | | references | + V | | + +----------+ | + | Shared | | + | database | | + +----------+ | + A | | + +---------+ refreshes | | references | + / /| | V | + +---------+ | +----------+ | +--------+ + | | | | |responses| | | + | | | | Name |---------|->|Foreign | + | Master |-------------->| Server | | |Resolver| + | files | | | |<--------|--| | + | |/ | | queries | +--------+ + +---------+ +----------+ | + A |maintenance | +--------+ + | +------------|->| | + | queries | |Foreign | + | | | Name | + +------------------|--| Server | + maintenance responses | +--------+ + +The shared database holds domain space data for the local name server +and resolver. The contents of the shared database will typically be a +mixture of authoritative data maintained by the periodic refresh +operations of the name server and cached data from previous resolver +requests. The structure of the domain data and the necessity for +synchronization between name servers and resolvers imply the general +characteristics of this database, but the actual format is up to the +local implementor. + + + + +Mockapetris [Page 6] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Information flow can also be tailored so that a group of hosts act +together to optimize activities. Sometimes this is done to offload less +capable hosts so that they do not have to implement a full resolver. +This can be appropriate for PCs or hosts which want to minimize the +amount of new network code which is required. This scheme can also +allow a group of hosts can share a small number of caches rather than +maintaining a large number of separate caches, on the premise that the +centralized caches will have a higher hit ratio. In either case, +resolvers are replaced with stub resolvers which act as front ends to +resolvers located in a recursive server in one or more name servers +known to perform that service: + + Local Hosts | Foreign + | + +---------+ | + | | responses | + | Stub |<--------------------+ | + | Resolver| | | + | |----------------+ | | + +---------+ recursive | | | + queries | | | + V | | + +---------+ recursive +----------+ | +--------+ + | | queries | |queries | | | + | Stub |-------------->| Recursive|---------|->|Foreign | + | Resolver| | Server | | | Name | + | |<--------------| |<--------|--| Server | + +---------+ responses | |responses| | | + +----------+ | +--------+ + | Central | | + | cache | | + +----------+ | + +In any case, note that domain components are always replicated for +reliability whenever possible. + +2.3. Conventions + +The domain system has several conventions dealing with low-level, but +fundamental, issues. While the implementor is free to violate these +conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in +ALL behavior observed from other hosts. + +2.3.1. Preferred name syntax + +The DNS specifications attempt to be as general as possible in the rules +for constructing domain names. The idea is that the name of any +existing object can be expressed as a domain name with minimal changes. + + + +Mockapetris [Page 7] + +RFC 1035 Domain Implementation and Specification November 1987 + + +However, when assigning a domain name for an object, the prudent user +will select a name which satisfies both the rules of the domain system +and any existing rules for the object, whether these rules are published +or implied by existing programs. + +For example, when naming a mail domain, the user should satisfy both the +rules of this memo and those in RFC-822. When creating a new host name, +the old rules for HOSTS.TXT should be followed. This avoids problems +when old software is converted to use domain names. + +The following syntax will result in fewer problems with many + +applications that use domain names (e.g., mail, TELNET). + +<domain> ::= <subdomain> | " " + +<subdomain> ::= <label> | <subdomain> "." <label> + +<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ] + +<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str> + +<let-dig-hyp> ::= <let-dig> | "-" + +<let-dig> ::= <letter> | <digit> + +<letter> ::= any one of the 52 alphabetic characters A through Z in +upper case and a through z in lower case + +<digit> ::= any one of the ten digits 0 through 9 + +Note that while upper and lower case letters are allowed in domain +names, no significance is attached to the case. That is, two names with +the same spelling but different case are to be treated as if identical. + +The labels must follow the rules for ARPANET host names. They must +start with a letter, end with a letter or digit, and have as interior +characters only letters, digits, and hyphen. There are also some +restrictions on the length. Labels must be 63 characters or less. + +For example, the following strings identify hosts in the Internet: + +A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA + +2.3.2. Data Transmission Order + +The order of transmission of the header and data described in this +document is resolved to the octet level. Whenever a diagram shows a + + + +Mockapetris [Page 8] + +RFC 1035 Domain Implementation and Specification November 1987 + + +group of octets, the order of transmission of those octets is the normal +order in which they are read in English. For example, in the following +diagram, the octets are transmitted in the order they are numbered. + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 1 | 2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 3 | 4 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 5 | 6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +Whenever an octet represents a numeric quantity, the left most bit in +the diagram is the high order or most significant bit. That is, the bit +labeled 0 is the most significant bit. For example, the following +diagram represents the value 170 (decimal). + + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |1 0 1 0 1 0 1 0| + +-+-+-+-+-+-+-+-+ + +Similarly, whenever a multi-octet field represents a numeric quantity +the left most bit of the whole field is the most significant bit. When +a multi-octet quantity is transmitted the most significant octet is +transmitted first. + +2.3.3. Character Case + +For all parts of the DNS that are part of the official protocol, all +comparisons between character strings (e.g., labels, domain names, etc.) +are done in a case-insensitive manner. At present, this rule is in +force throughout the domain system without exception. However, future +additions beyond current usage may need to use the full binary octet +capabilities in names, so attempts to store domain names in 7-bit ASCII +or use of special bytes to terminate labels, etc., should be avoided. + +When data enters the domain system, its original case should be +preserved whenever possible. In certain circumstances this cannot be +done. For example, if two RRs are stored in a database, one at x.y and +one at X.Y, they are actually stored at the same place in the database, +and hence only one casing would be preserved. The basic rule is that +case can be discarded only when data is used to define structure in a +database, and two names are identical when compared in a case +insensitive manner. + + + + +Mockapetris [Page 9] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Loss of case sensitive data must be minimized. Thus while data for x.y +and X.Y may both be stored under a single location x.y or X.Y, data for +a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In +general, this preserves the case of the first label of a domain name, +but forces standardization of interior node labels. + +Systems administrators who enter data into the domain database should +take care to represent the data they supply to the domain system in a +case-consistent manner if their system is case-sensitive. The data +distribution system in the domain system will ensure that consistent +representations are preserved. + +2.3.4. Size limits + +Various objects and parameters in the DNS have size limits. They are +listed below. Some could be easily changed, others are more +fundamental. + +labels 63 octets or less + +names 255 octets or less + +TTL positive values of a signed 32 bit number. + +UDP messages 512 octets or less + +3. DOMAIN NAME SPACE AND RR DEFINITIONS + +3.1. Name space definitions + +Domain names in messages are expressed in terms of a sequence of labels. +Each label is represented as a one octet length field followed by that +number of octets. Since every domain name ends with the null label of +the root, a domain name is terminated by a length byte of zero. The +high order two bits of every length octet must be zero, and the +remaining six bits of the length field limit the label to 63 octets or +less. + +To simplify implementations, the total length of a domain name (i.e., +label octets and label length octets) is restricted to 255 octets or +less. + +Although labels can contain any 8 bit values in octets that make up a +label, it is strongly recommended that labels follow the preferred +syntax described elsewhere in this memo, which is compatible with +existing host naming conventions. Name servers and resolvers must +compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII +with zero parity. Non-alphabetic codes must match exactly. + + + +Mockapetris [Page 10] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.2. RR definitions + +3.2.1. Format + +All RRs have the same top level format shown below: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +where: + +NAME an owner name, i.e., the name of the node to which this + resource record pertains. + +TYPE two octets containing one of the RR TYPE codes. + +CLASS two octets containing one of the RR CLASS codes. + +TTL a 32 bit signed integer that specifies the time interval + that the resource record may be cached before the source + of the information should again be consulted. Zero + values are interpreted to mean that the RR can only be + used for the transaction in progress, and should not be + cached. For example, SOA records are always distributed + with a zero TTL to prohibit caching. Zero values can + also be used for extremely volatile data. + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + + + +Mockapetris [Page 11] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + +3.2.2. TYPE values + +TYPE fields are used in resource records. Note that these types are a +subset of QTYPEs. + +TYPE value and meaning + +A 1 a host address + +NS 2 an authoritative name server + +MD 3 a mail destination (Obsolete - use MX) + +MF 4 a mail forwarder (Obsolete - use MX) + +CNAME 5 the canonical name for an alias + +SOA 6 marks the start of a zone of authority + +MB 7 a mailbox domain name (EXPERIMENTAL) + +MG 8 a mail group member (EXPERIMENTAL) + +MR 9 a mail rename domain name (EXPERIMENTAL) + +NULL 10 a null RR (EXPERIMENTAL) + +WKS 11 a well known service description + +PTR 12 a domain name pointer + +HINFO 13 host information + +MINFO 14 mailbox or mail list information + +MX 15 mail exchange + +TXT 16 text strings + +3.2.3. QTYPE values + +QTYPE fields appear in the question part of a query. QTYPES are a +superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the +following QTYPEs are defined: + + + +Mockapetris [Page 12] + +RFC 1035 Domain Implementation and Specification November 1987 + + +AXFR 252 A request for a transfer of an entire zone + +MAILB 253 A request for mailbox-related records (MB, MG or MR) + +MAILA 254 A request for mail agent RRs (Obsolete - see MX) + +* 255 A request for all records + +3.2.4. CLASS values + +CLASS fields appear in resource records. The following CLASS mnemonics +and values are defined: + +IN 1 the Internet + +CS 2 the CSNET class (Obsolete - used only for examples in + some obsolete RFCs) + +CH 3 the CHAOS class + +HS 4 Hesiod [Dyer 87] + +3.2.5. QCLASS values + +QCLASS fields appear in the question section of a query. QCLASS values +are a superset of CLASS values; every CLASS is a valid QCLASS. In +addition to CLASS values, the following QCLASSes are defined: + +* 255 any class + +3.3. Standard RRs + +The following RR definitions are expected to occur, at least +potentially, in all classes. In particular, NS, SOA, CNAME, and PTR +will be used in all classes, and have the same format in all classes. +Because their RDATA format is known, all domain names in the RDATA +section of these RRs may be compressed. + +<domain-name> is a domain name represented as a series of labels, and +terminated by a label with zero length. <character-string> is a single +length octet followed by that number of characters. <character-string> +is treated as binary information, and can be up to 256 characters in +length (including the length octet). + + + + + + + + +Mockapetris [Page 13] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.1. CNAME RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CNAME A <domain-name> which specifies the canonical or primary + name for the owner. The owner name is an alias. + +CNAME RRs cause no additional section processing, but name servers may +choose to restart the query at the canonical name in certain cases. See +the description of name server logic in [RFC-1034] for details. + +3.3.2. HINFO RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / CPU / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / OS / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +CPU A <character-string> which specifies the CPU type. + +OS A <character-string> which specifies the operating + system type. + +Standard values for CPU and OS can be found in [RFC-1010]. + +HINFO records are used to acquire general information about a host. The +main use is for protocols such as FTP that can use special procedures +when talking between machines or operating systems of the same type. + +3.3.3. MB RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has the + specified mailbox. + + + +Mockapetris [Page 14] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MB records cause additional section processing which looks up an A type +RRs corresponding to MADNAME. + +3.3.4. MD RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which should be able to deliver + mail for the domain. + +MD records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MD is obsolete. See the definition of MX and [RFC-974] for details of +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 0. + +3.3.5. MF RDATA format (Obsolete) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MADNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MADNAME A <domain-name> which specifies a host which has a mail + agent for the domain which will accept mail for + forwarding to the domain. + +MF records cause additional section processing which looks up an A type +record corresponding to MADNAME. + +MF is obsolete. See the definition of MX and [RFC-974] for details ofw +the new scheme. The recommended policy for dealing with MD RRs found in +a master file is to reject them, or to convert them to MX RRs with a +preference of 10. + + + + + + + +Mockapetris [Page 15] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.6. MG RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MGMNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MGMNAME A <domain-name> which specifies a mailbox which is a + member of the mail group specified by the domain name. + +MG records cause no additional section processing. + +3.3.7. MINFO RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EMAILBX / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +RMAILBX A <domain-name> which specifies a mailbox which is + responsible for the mailing list or mailbox. If this + domain name names the root, the owner of the MINFO RR is + responsible for itself. Note that many existing mailing + lists use a mailbox X-request for the RMAILBX field of + mailing list X, e.g., Msgroup-request for Msgroup. This + field provides a more general mechanism. + + +EMAILBX A <domain-name> which specifies a mailbox which is to + receive error messages related to the mailing list or + mailbox specified by the owner of the MINFO RR (similar + to the ERRORS-TO: field which has been proposed). If + this domain name names the root, errors should be + returned to the sender of the message. + +MINFO records cause no additional section processing. Although these +records can be associated with a simple mailbox, they are usually used +with a mailing list. + + + + + + + + +Mockapetris [Page 16] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.8. MR RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NEWNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NEWNAME A <domain-name> which specifies a mailbox which is the + proper rename of the specified mailbox. + +MR records cause no additional section processing. The main use for MR +is as a forwarding entry for a user who has moved to a different +mailbox. + +3.3.9. MX RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PREFERENCE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / EXCHANGE / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PREFERENCE A 16 bit integer which specifies the preference given to + this RR among others at the same owner. Lower values + are preferred. + +EXCHANGE A <domain-name> which specifies a host willing to act as + a mail exchange for the owner name. + +MX records cause type A additional section processing for the host +specified by EXCHANGE. The use of MX RRs is explained in detail in +[RFC-974]. + +3.3.10. NULL RDATA format (EXPERIMENTAL) + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / <anything> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +Anything at all may be in the RDATA field so long as it is 65535 octets +or less. + + + + +Mockapetris [Page 17] + +RFC 1035 Domain Implementation and Specification November 1987 + + +NULL records cause no additional section processing. NULL RRs are not +allowed in master files. NULLs are used as placeholders in some +experimental extensions of the DNS. + +3.3.11. NS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / NSDNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NSDNAME A <domain-name> which specifies a host which should be + authoritative for the specified class and domain. + +NS records cause both the usual additional section processing to locate +a type A record, and, when used in a referral, a special search of the +zone in which they reside for glue information. + +The NS RR states that the named host should be expected to have a zone +starting at owner name of the specified class. Note that the class may +not indicate the protocol family which should be used to communicate +with the host, although it is typically a strong hint. For example, +hosts which are name servers for either Internet (IN) or Hesiod (HS) +class information are normally queried using IN class protocols. + +3.3.12. PTR RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / PTRDNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +PTRDNAME A <domain-name> which points to some location in the + domain name space. + +PTR records cause no additional section processing. These RRs are used +in special domains to point to some other location in the domain space. +These records are simple data, and don't imply any special processing +similar to that performed by CNAME, which identifies aliases. See the +description of the IN-ADDR.ARPA domain for an example. + + + + + + + + +Mockapetris [Page 18] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.3.13. SOA RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / MNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / RNAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | SERIAL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | REFRESH | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RETRY | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | EXPIRE | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | MINIMUM | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +MNAME The <domain-name> of the name server that was the + original or primary source of data for this zone. + +RNAME A <domain-name> which specifies the mailbox of the + person responsible for this zone. + +SERIAL The unsigned 32 bit version number of the original copy + of the zone. Zone transfers preserve this value. This + value wraps and should be compared using sequence space + arithmetic. + +REFRESH A 32 bit time interval before the zone should be + refreshed. + +RETRY A 32 bit time interval that should elapse before a + failed refresh should be retried. + +EXPIRE A 32 bit time value that specifies the upper limit on + the time interval that can elapse before the zone is no + longer authoritative. + + + + + +Mockapetris [Page 19] + +RFC 1035 Domain Implementation and Specification November 1987 + + +MINIMUM The unsigned 32 bit minimum TTL field that should be + exported with any RR from this zone. + +SOA records cause no additional section processing. + +All times are in units of seconds. + +Most of these fields are pertinent only for name server maintenance +operations. However, MINIMUM is used in all query operations that +retrieve RRs from a zone. Whenever a RR is sent in a response to a +query, the TTL field is set to the maximum of the TTL field from the RR +and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower +bound on the TTL field for all RRs in a zone. Note that this use of +MINIMUM should occur when the RRs are copied into the response and not +when the zone is loaded from a master file or via a zone transfer. The +reason for this provison is to allow future dynamic update facilities to +change the SOA RR with known semantics. + + +3.3.14. TXT RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / TXT-DATA / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +TXT-DATA One or more <character-string>s. + +TXT RRs are used to hold descriptive text. The semantics of the text +depends on the domain where it is found. + +3.4. Internet specific RRs + +3.4.1. A RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS A 32 bit Internet address. + +Hosts that have multiple Internet addresses will have multiple A +records. + + + + + +Mockapetris [Page 20] + +RFC 1035 Domain Implementation and Specification November 1987 + + +A records cause no additional section processing. The RDATA section of +an A line in a master file is an Internet address expressed as four +decimal numbers separated by dots without any embedded spaces (e.g., +"10.2.0.52" or "192.0.5.6"). + +3.4.2. WKS RDATA format + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ADDRESS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | PROTOCOL | | + +--+--+--+--+--+--+--+--+ | + | | + / <BIT MAP> / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ADDRESS An 32 bit Internet address + +PROTOCOL An 8 bit IP protocol number + +<BIT MAP> A variable length bit map. The bit map must be a + multiple of 8 bits long. + +The WKS record is used to describe the well known services supported by +a particular protocol on a particular internet address. The PROTOCOL +field specifies an IP protocol number, and the bit map has one bit per +port of the specified protocol. The first bit corresponds to port 0, +the second to port 1, etc. If the bit map does not include a bit for a +protocol of interest, that bit is assumed zero. The appropriate values +and mnemonics for ports and protocols are specified in [RFC-1010]. + +For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port +25 (SMTP). If this bit is set, a SMTP server should be listening on TCP +port 25; if zero, SMTP service is not supported on the specified +address. + +The purpose of WKS RRs is to provide availability information for +servers for TCP and UDP. If a server supports both TCP and UDP, or has +multiple Internet addresses, then multiple WKS RRs are used. + +WKS RRs cause no additional section processing. + +In master files, both ports and protocols are expressed using mnemonics +or decimal numbers. + + + + +Mockapetris [Page 21] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.5. IN-ADDR.ARPA domain + +The Internet uses a special domain to support gateway location and +Internet address to host mapping. Other classes may employ a similar +strategy in other domains. The intent of this domain is to provide a +guaranteed method to perform host address to host name mapping, and to +facilitate queries to locate all gateways on a particular network in the +Internet. + +Note that both of these services are similar to functions that could be +performed by inverse queries; the difference is that this part of the +domain name space is structured according to address, and hence can +guarantee that the appropriate data can be located without an exhaustive +search of the domain space. + +The domain begins at IN-ADDR.ARPA and has a substructure which follows +the Internet addressing structure. + +Domain names in the IN-ADDR.ARPA domain are defined to have up to four +labels in addition to the IN-ADDR.ARPA suffix. Each label represents +one octet of an Internet address, and is expressed as a character string +for a decimal value in the range 0-255 (with leading zeros omitted +except in the case of a zero octet which is represented by a single +zero). + +Host addresses are represented by domain names that have all four labels +specified. Thus data for Internet address 10.2.0.52 is located at +domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to +read, allows zones to be delegated which are exactly one network of +address space. For example, 10.IN-ADDR.ARPA can be a zone containing +data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for +MILNET. Address nodes are used to hold pointers to primary host names +in the normal domain space. + +Network numbers correspond to some non-terminal nodes at various depths +in the IN-ADDR.ARPA domain, since Internet network numbers are either 1, +2, or 3 octets. Network nodes are used to hold pointers to the primary +host names of gateways attached to that network. Since a gateway is, by +definition, on more than one network, it will typically have two or more +network nodes which point at it. Gateways will also have host level +pointers at their fully qualified addresses. + +Both the gateway pointers at network nodes and the normal host pointers +at full address nodes use the PTR RR to point back to the primary domain +names of the corresponding hosts. + +For example, the IN-ADDR.ARPA domain will contain information about the +ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's + + + +Mockapetris [Page 22] + +RFC 1035 Domain Implementation and Specification November 1987 + + +net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI +gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET- +GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4 +and a name GW.LCS.MIT.EDU, the domain database would contain: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU. + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Thus a program which wanted to locate gateways on net 10 would originate +a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It +would receive two RRs in response: + + 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU. + 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU. + +The program could then originate QTYPE=A, QCLASS=IN queries for MILNET- +GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of +these gateways. + +A resolver which wanted to find the host name corresponding to Internet +host address 10.0.0.6 would pursue a query of the form QTYPE=PTR, +QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive: + + 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU. + +Several cautions apply to the use of these services: + - Since the IN-ADDR.ARPA special domain and the normal domain + for a particular host or gateway will be in different zones, + the possibility exists that that the data may be inconsistent. + + - Gateways will often have two names in separate domains, only + one of which can be primary. + + - Systems that use the domain database to initialize their + routing tables must start with enough gateway information to + guarantee that they can access the appropriate name server. + + - The gateway data only reflects the existence of a gateway in a + manner equivalent to the current HOSTS.TXT file. It doesn't + replace the dynamic availability information from GGP or EGP. + + + +Mockapetris [Page 23] + +RFC 1035 Domain Implementation and Specification November 1987 + + +3.6. Defining new types, classes, and special namespaces + +The previously defined types and classes are the ones in use as of the +date of this memo. New definitions should be expected. This section +makes some recommendations to designers considering additions to the +existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the +forum where general discussion of design issues takes place. + +In general, a new type is appropriate when new information is to be +added to the database about an existing object, or we need new data +formats for some totally new object. Designers should attempt to define +types and their RDATA formats that are generally applicable to all +classes, and which avoid duplication of information. New classes are +appropriate when the DNS is to be used for a new protocol, etc which +requires new class-specific data formats, or when a copy of the existing +name space is desired, but a separate management domain is necessary. + +New types and classes need mnemonics for master files; the format of the +master files requires that the mnemonics for type and class be disjoint. + +TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes +respectively. + +The present system uses multiple RRs to represent multiple values of a +type rather than storing multiple values in the RDATA section of a +single RR. This is less efficient for most applications, but does keep +RRs shorter. The multiple RRs assumption is incorporated in some +experimental work on dynamic update methods. + +The present system attempts to minimize the duplication of data in the +database in order to insure consistency. Thus, in order to find the +address of the host for a mail exchange, you map the mail domain name to +a host name, then the host name to addresses, rather than a direct +mapping to host address. This approach is preferred because it avoids +the opportunity for inconsistency. + +In defining a new type of data, multiple RR types should not be used to +create an ordering between entries or express different formats for +equivalent bindings, instead this information should be carried in the +body of the RR and a single type used. This policy avoids problems with +caching multiple types and defining QTYPEs to match multiple types. + +For example, the original form of mail exchange binding used two RR +types one to represent a "closer" exchange (MD) and one to represent a +"less close" exchange (MF). The difficulty is that the presence of one +RR type in a cache doesn't convey any information about the other +because the query which acquired the cached information might have used +a QTYPE of MF, MD, or MAILA (which matched both). The redesigned + + + +Mockapetris [Page 24] + +RFC 1035 Domain Implementation and Specification November 1987 + + +service used a single type (MX) with a "preference" value in the RDATA +section which can order different RRs. However, if any MX RRs are found +in the cache, then all should be there. + +4. MESSAGES + +4.1. Format + +All communications inside of the domain protocol are carried in a single +format called a message. The top level format of message is divided +into 5 sections (some of which are empty in certain cases) shown below: + + +---------------------+ + | Header | + +---------------------+ + | Question | the question for the name server + +---------------------+ + | Answer | RRs answering the question + +---------------------+ + | Authority | RRs pointing toward an authority + +---------------------+ + | Additional | RRs holding additional information + +---------------------+ + +The header section is always present. The header includes fields that +specify which of the remaining sections are present, and also specify +whether the message is a query or a response, a standard query or some +other opcode, etc. + +The names of the sections after the header are derived from their use in +standard queries. The question section contains fields that describe a +question to a name server. These fields are a query type (QTYPE), a +query class (QCLASS), and a query domain name (QNAME). The last three +sections have the same format: a possibly empty list of concatenated +resource records (RRs). The answer section contains RRs that answer the +question; the authority section contains RRs that point toward an +authoritative name server; the additional records section contains RRs +which relate to the query, but are not strictly answers for the +question. + + + + + + + + + + + + +Mockapetris [Page 25] + +RFC 1035 Domain Implementation and Specification November 1987 + + +4.1.1. Header section format + +The header contains the following fields: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +ID A 16 bit identifier assigned by the program that + generates any kind of query. This identifier is copied + the corresponding reply and can be used by the requester + to match up replies to outstanding queries. + +QR A one bit field that specifies whether this message is a + query (0), or a response (1). + +OPCODE A four bit field that specifies kind of query in this + message. This value is set by the originator of a query + and copied into the response. The values are: + + 0 a standard query (QUERY) + + 1 an inverse query (IQUERY) + + 2 a server status request (STATUS) + + 3-15 reserved for future use + +AA Authoritative Answer - this bit is valid in responses, + and specifies that the responding name server is an + authority for the domain name in question section. + + Note that the contents of the answer section may have + multiple owner names because of aliases. The AA bit + + + +Mockapetris [Page 26] + +RFC 1035 Domain Implementation and Specification November 1987 + + + corresponds to the name which matches the query name, or + the first owner name in the answer section. + +TC TrunCation - specifies that this message was truncated + due to length greater than that permitted on the + transmission channel. + +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. + +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. + +Z Reserved for future use. Must be zero in all queries + and responses. + +RCODE Response code - this 4 bit field is set as part of + responses. The values have the following + interpretation: + + 0 No error condition + + 1 Format error - The name server was + unable to interpret the query. + + 2 Server failure - The name server was + unable to process this query due to a + problem with the name server. + + 3 Name Error - Meaningful only for + responses from an authoritative name + server, this code signifies that the + domain name referenced in the query does + not exist. + + 4 Not Implemented - The name server does + not support the requested kind of query. + + 5 Refused - The name server refuses to + perform the specified operation for + policy reasons. For example, a name + server may not wish to provide the + information to the particular requester, + or a name server may not wish to perform + a particular operation (e.g., zone + + + +Mockapetris [Page 27] + +RFC 1035 Domain Implementation and Specification November 1987 + + + transfer) for particular data. + + 6-15 Reserved for future use. + +QDCOUNT an unsigned 16 bit integer specifying the number of + entries in the question section. + +ANCOUNT an unsigned 16 bit integer specifying the number of + resource records in the answer section. + +NSCOUNT an unsigned 16 bit integer specifying the number of name + server resource records in the authority records + section. + +ARCOUNT an unsigned 16 bit integer specifying the number of + resource records in the additional records section. + +4.1.2. Question section format + +The question section is used to carry the "question" in most queries, +i.e., the parameters that define what is being asked. The section +contains QDCOUNT (usually 1) entries, each of the following format: + + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + +QTYPE a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR. + + + +Mockapetris [Page 28] + +RFC 1035 Domain Implementation and Specification November 1987 + + +QCLASS a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same +format: a variable number of resource records, where the number of +records is specified in the corresponding count field in the header. +Each resource record has the following format: + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +where: + +NAME a domain name to which this resource record pertains. + +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA + field. + +CLASS two octets which specify the class of the data in the + RDATA field. + +TTL a 32 bit unsigned integer that specifies the time + interval (in seconds) that the resource record may be + cached before it should be discarded. Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached. + + + + + +Mockapetris [Page 29] + +RFC 1035 Domain Implementation and Specification November 1987 + + +RDLENGTH an unsigned 16 bit integer that specifies the length in + octets of the RDATA field. + +RDATA a variable length string of octets that describes the + resource. The format of this information varies + according to the TYPE and CLASS of the resource record. + For example, the if the TYPE is A and the CLASS is IN, + the RDATA field is a 4 octet ARPA Internet address. + +4.1.4. Message compression + +In order to reduce the size of messages, the domain system utilizes a +compression scheme which eliminates the repetition of domain names in a +message. In this scheme, an entire domain name or a list of labels at +the end of a domain name is replaced with a pointer to a prior occurrence +of the same name. + +The pointer takes the form of a two octet sequence: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. (The 10 and 01 combinations +are reserved for future use.) The OFFSET field specifies an offset from +the start of the message (i.e., the first octet of the ID field in the +domain header). A zero offset specifies the first byte of the ID field, +etc. + +The compression scheme allows a domain name in a message to be +represented as either: + + - a sequence of labels ending in a zero octet + + - a pointer + + - a sequence of labels ending with a pointer + +Pointers can only be used for occurrences of a domain name where the +format is not class specific. If this were not the case, a name server +or resolver would be required to know the format of all RRs it handled. +As yet, there are no such cases, but they may occur in future RDATA +formats. + +If a domain name is contained in a part of the message subject to a +length field (such as the RDATA section of an RR), and compression is + + + +Mockapetris [Page 30] + +RFC 1035 Domain Implementation and Specification November 1987 + + +used, the length of the compressed name is used in the length +calculation, rather than the length of the expanded name. + +Programs are free to avoid using pointers in messages they generate, +although this will reduce datagram capacity, and may cause truncation. +However all programs are required to understand arriving messages that +contain pointers. + +For example, a datagram might need to use the domain names F.ISI.ARPA, +FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the +message, these domain names might be represented as: + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 20 | 1 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 22 | 3 | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 24 | S | I | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 26 | 4 | A | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 28 | R | P | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 30 | A | 0 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 40 | 3 | F | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 42 | O | O | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 44 | 1 1| 20 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 64 | 1 1| 26 | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + 92 | 0 | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +The domain name for F.ISI.ARPA is shown at offset 20. The domain name +FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to +concatenate a label for FOO to the previously defined F.ISI.ARPA. The +domain name ARPA is defined at offset 64 using a pointer to the ARPA +component of the name F.ISI.ARPA at 20; note that this pointer relies on +ARPA being the last label in the string at 20. The root domain name is + + + +Mockapetris [Page 31] + +RFC 1035 Domain Implementation and Specification November 1987 + + +defined by a single octet of zeros at 92; the root domain name has no +labels. + +4.2. Transport + +The DNS assumes that messages will be transmitted as datagrams or in a +byte stream carried by a virtual circuit. While virtual circuits can be +used for any DNS activity, datagrams are preferred for queries due to +their lower overhead and better performance. Zone refresh activities +must use virtual circuits because of the need for reliable transfer. + +The Internet supports name server access using TCP [RFC-793] on server +port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP +port 53 (decimal). + +4.2.1. UDP usage + +Messages sent using UDP user server port 53 (decimal). + +Messages carried by UDP are restricted to 512 bytes (not counting the IP +or UDP headers). Longer messages are truncated and the TC bit is set in +the header. + +UDP is not acceptable for zone transfers, but is the recommended method +for standard queries in the Internet. Queries sent using UDP may be +lost, and hence a retransmission strategy is required. Queries or their +responses may be reordered by the network, or by processing in name +servers, so resolvers should not depend on them being returned in order. + +The optimal UDP retransmission policy will vary with performance of the +Internet and the needs of the client, but the following are recommended: + + - The client should try other servers and server addresses + before repeating a query to a specific address of a server. + + - The retransmission interval should be based on prior + statistics if possible. Too aggressive retransmission can + easily slow responses for the community at large. Depending + on how well connected the client is to its expected servers, + the minimum retransmission interval should be 2-5 seconds. + +More suggestions on server selection and retransmission policy can be +found in the resolver section of this memo. + +4.2.2. TCP usage + +Messages sent over TCP connections use server port 53 (decimal). The +message is prefixed with a two byte length field which gives the message + + + +Mockapetris [Page 32] + +RFC 1035 Domain Implementation and Specification November 1987 + + +length, excluding the two byte length field. This length field allows +the low-level processing to assemble a complete message before beginning +to parse it. + +Several connection management policies are recommended: + + - The server should not block other activities waiting for TCP + data. + + - The server should support multiple connections. + + - The server should assume that the client will initiate + connection closing, and should delay closing its end of the + connection until all outstanding client requests have been + satisfied. + + - If the server needs to close a dormant connection to reclaim + resources, it should wait until the connection has been idle + for a period on the order of two minutes. In particular, the + server should allow the SOA and AXFR request sequence (which + begins a refresh operation) to be made on a single connection. + Since the server would be unable to answer queries anyway, a + unilateral close or reset may be used instead of a graceful + close. + +5. MASTER FILES + +Master files are text files that contain RRs in text form. Since the +contents of a zone can be expressed in the form of a list of RRs a +master file is most often used to define a zone, though it can be used +to list a cache's contents. Hence, this section first discusses the +format of RRs in a master file, and then the special considerations when +a master file is used to create a zone in some name server. + +5.1. Format + +The format of these files is a sequence of entries. Entries are +predominantly line-oriented, though parentheses can be used to continue +a list of items across a line boundary, and text literals can contain +CRLF within the text. Any combination of tabs and spaces act as a +delimiter between the separate items that make up an entry. The end of +any line in the master file can end with a comment. The comment starts +with a ";" (semicolon). + +The following entries are defined: + + <blank>[<comment>] + + + + +Mockapetris [Page 33] + +RFC 1035 Domain Implementation and Specification November 1987 + + + $ORIGIN <domain-name> [<comment>] + + $INCLUDE <file-name> [<domain-name>] [<comment>] + + <domain-name><rr> [<comment>] + + <blank><rr> [<comment>] + +Blank lines, with or without comments, are allowed anywhere in the file. + +Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is +followed by a domain name, and resets the current origin for relative +domain names to the stated name. $INCLUDE inserts the named file into +the current file, and may optionally specify a domain name that sets the +relative domain name origin for the included file. $INCLUDE may also +have a comment. Note that a $INCLUDE entry never changes the relative +origin of the parent file, regardless of changes to the relative origin +made within the included file. + +The last two forms represent RRs. If an entry for an RR begins with a +blank, then the RR is assumed to be owned by the last stated owner. If +an RR entry begins with a <domain-name>, then the owner name is reset. + +<rr> contents take one of the following forms: + + [<TTL>] [<class>] <type> <RDATA> + + [<class>] [<TTL>] <type> <RDATA> + +The RR begins with optional TTL and class fields, followed by a type and +RDATA field appropriate to the type and class. Class and type use the +standard mnemonics, TTL is a decimal integer. Omitted class and TTL +values are default to the last explicitly stated values. Since type and +class mnemonics are disjoint, the parse is unique. (Note that this +order is different from the order used in examples and the order used in +the actual RRs; the given order allows easier parsing and defaulting.) + +<domain-name>s make up a large share of the data in the master file. +The labels in the domain name are expressed as character strings and +separated by dots. Quoting conventions allow arbitrary characters to be +stored in domain names. Domain names that end in a dot are called +absolute, and are taken as complete. Domain names which do not end in a +dot are called relative; the actual domain name is the concatenation of +the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as +an argument to the master file loading routine. A relative name is an +error when no origin is available. + + + + + +Mockapetris [Page 34] + +RFC 1035 Domain Implementation and Specification November 1987 + + +<character-string> is expressed in one or two ways: as a contiguous set +of characters without interior spaces, or as a string beginning with a " +and ending with a ". Inside a " delimited string any character can +occur, except for a " itself, which must be quoted using \ (back slash). + +Because these files are text files several special encodings are +necessary to allow arbitrary data to be loaded. In particular: + + of the root. + +@ A free standing @ is used to denote the current origin. + +\X where X is any character other than a digit (0-9), is + used to quote that character so that its special meaning + does not apply. For example, "\." can be used to place + a dot character in a label. + +\DDD where each D is a digit is the octet corresponding to + the decimal number described by DDD. The resulting + octet is assumed to be text and is not checked for + special meaning. + +( ) Parentheses are used to group data that crosses a line + boundary. In effect, line terminations are not + recognized within parentheses. + +; Semicolon is used to start a comment; the remainder of + the line is ignored. + +5.2. Use of master files to define zones + +When a master file is used to load a zone, the operation should be +suppressed if any errors are encountered in the master file. The +rationale for this is that a single error can have widespread +consequences. For example, suppose that the RRs defining a delegation +have syntax errors; then the server will return authoritative name +errors for all names in the subzone (except in the case where the +subzone is also present on the server). + +Several other validity checks that should be performed in addition to +insuring that the file is syntactically correct: + + 1. All RRs in the file should have the same class. + + 2. Exactly one SOA RR should be present at the top of the zone. + + 3. If delegations are present and glue information is required, + it should be present. + + + +Mockapetris [Page 35] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 4. Information present outside of the authoritative nodes in the + zone should be glue information, rather than the result of an + origin or similar error. + +5.3. Master file example + +The following is an example file which might be used to define the +ISI.EDU zone.and is loaded with an origin of ISI.EDU: + +@ IN SOA VENERA Action\.domains ( + 20 ; SERIAL + 7200 ; REFRESH + 600 ; RETRY + 3600000; EXPIRE + 60) ; MINIMUM + + NS A.ISI.EDU. + NS VENERA + NS VAXA + MX 10 VENERA + MX 20 VAXA + +A A 26.3.0.103 + +VENERA A 10.1.0.52 + A 128.9.0.32 + +VAXA A 10.2.0.27 + A 128.9.0.33 + + +$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT + +Where the file <SUBSYS>ISI-MAILBOXES.TXT is: + + MOE MB A.ISI.EDU. + LARRY MB A.ISI.EDU. + CURLEY MB A.ISI.EDU. + STOOGES MG MOE + MG LARRY + MG CURLEY + +Note the use of the \ character in the SOA RR to specify the responsible +person mailbox "Action.domains@E.ISI.EDU". + + + + + + + +Mockapetris [Page 36] + +RFC 1035 Domain Implementation and Specification November 1987 + + +6. NAME SERVER IMPLEMENTATION + +6.1. Architecture + +The optimal structure for the name server will depend on the host +operating system and whether the name server is integrated with resolver +operations, either by supporting recursive service, or by sharing its +database with a resolver. This section discusses implementation +considerations for a name server which shares a database with a +resolver, but most of these concerns are present in any name server. + +6.1.1. Control + +A name server must employ multiple concurrent activities, whether they +are implemented as separate tasks in the host's OS or multiplexing +inside a single name server program. It is simply not acceptable for a +name server to block the service of UDP requests while it waits for TCP +data for refreshing or query activities. Similarly, a name server +should not attempt to provide recursive service without processing such +requests in parallel, though it may choose to serialize requests from a +single client, or to regard identical requests from the same client as +duplicates. A name server should not substantially delay requests while +it reloads a zone from master files or while it incorporates a newly +refreshed zone into its database. + +6.1.2. Database + +While name server implementations are free to use any internal data +structures they choose, the suggested structure consists of three major +parts: + + - A "catalog" data structure which lists the zones available to + this server, and a "pointer" to the zone data structure. The + main purpose of this structure is to find the nearest ancestor + zone, if any, for arriving standard queries. + + - Separate data structures for each of the zones held by the + name server. + + - A data structure for cached data. (or perhaps separate caches + for different classes) + +All of these data structures can be implemented an identical tree +structure format, with different data chained off the nodes in different +parts: in the catalog the data is pointers to zones, while in the zone +and cache data structures, the data will be RRs. In designing the tree +framework the designer should recognize that query processing will need +to traverse the tree using case-insensitive label comparisons; and that + + + +Mockapetris [Page 37] + +RFC 1035 Domain Implementation and Specification November 1987 + + +in real data, a few nodes have a very high branching factor (100-1000 or +more), but the vast majority have a very low branching factor (0-1). + +One way to solve the case problem is to store the labels for each node +in two pieces: a standardized-case representation of the label where all +ASCII characters are in a single case, together with a bit mask that +denotes which characters are actually of a different case. The +branching factor diversity can be handled using a simple linked list for +a node until the branching factor exceeds some threshold, and +transitioning to a hash structure after the threshold is exceeded. In +any case, hash structures used to store tree sections must insure that +hash functions and procedures preserve the casing conventions of the +DNS. + +The use of separate structures for the different parts of the database +is motivated by several factors: + + - The catalog structure can be an almost static structure that + need change only when the system administrator changes the + zones supported by the server. This structure can also be + used to store parameters used to control refreshing + activities. + + - The individual data structures for zones allow a zone to be + replaced simply by changing a pointer in the catalog. Zone + refresh operations can build a new structure and, when + complete, splice it into the database via a simple pointer + replacement. It is very important that when a zone is + refreshed, queries should not use old and new data + simultaneously. + + - With the proper search procedures, authoritative data in zones + will always "hide", and hence take precedence over, cached + data. + + - Errors in zone definitions that cause overlapping zones, etc., + may cause erroneous responses to queries, but problem + determination is simplified, and the contents of one "bad" + zone can't corrupt another. + + - Since the cache is most frequently updated, it is most + vulnerable to corruption during system restarts. It can also + become full of expired RR data. In either case, it can easily + be discarded without disturbing zone data. + +A major aspect of database design is selecting a structure which allows +the name server to deal with crashes of the name server's host. State +information which a name server should save across system crashes + + + +Mockapetris [Page 38] + +RFC 1035 Domain Implementation and Specification November 1987 + + +includes the catalog structure (including the state of refreshing for +each zone) and the zone data itself. + +6.1.3. Time + +Both the TTL data for RRs and the timing data for refreshing activities +depends on 32 bit timers in units of seconds. Inside the database, +refresh timers and TTLs for cached data conceptually "count down", while +data in the zone stays with constant TTLs. + +A recommended implementation strategy is to store time in two ways: as +a relative increment and as an absolute time. One way to do this is to +use positive 32 bit numbers for one type and negative numbers for the +other. The RRs in zones use relative times; the refresh timers and +cache data use absolute times. Absolute numbers are taken with respect +to some known origin and converted to relative values when placed in the +response to a query. When an absolute TTL is negative after conversion +to relative, then the data is expired and should be ignored. + +6.2. Standard query processing + +The major algorithm for standard query processing is presented in +[RFC-1034]. + +When processing queries with QCLASS=*, or some other QCLASS which +matches multiple classes, the response should never be authoritative +unless the server can guarantee that the response covers all classes. + +When composing a response, RRs which are to be inserted in the +additional section, but duplicate RRs in the answer or authority +sections, may be omitted from the additional section. + +When a response is so long that truncation is required, the truncation +should start at the end of the response and work forward in the +datagram. Thus if there is any data for the authority section, the +answer section is guaranteed to be unique. + +The MINIMUM value in the SOA should be used to set a floor on the TTL of +data distributed from a zone. This floor function should be done when +the data is copied into a response. This will allow future dynamic +update protocols to change the SOA MINIMUM field without ambiguous +semantics. + +6.3. Zone refresh and reload processing + +In spite of a server's best efforts, it may be unable to load zone data +from a master file due to syntax errors, etc., or be unable to refresh a +zone within the its expiration parameter. In this case, the name server + + + +Mockapetris [Page 39] + +RFC 1035 Domain Implementation and Specification November 1987 + + +should answer queries as if it were not supposed to possess the zone. + +If a master is sending a zone out via AXFR, and a new version is created +during the transfer, the master should continue to send the old version +if possible. In any case, it should never send part of one version and +part of another. If completion is not possible, the master should reset +the connection on which the zone transfer is taking place. + +6.4. Inverse queries (Optional) + +Inverse queries are an optional part of the DNS. Name servers are not +required to support any form of inverse queries. If a name server +receives an inverse query that it does not support, it returns an error +response with the "Not Implemented" error set in the header. While +inverse query support is optional, all name servers must be at least +able to return the error response. + +6.4.1. The contents of inverse queries and responses Inverse +queries reverse the mappings performed by standard query operations; +while a standard query maps a domain name to a resource, an inverse +query maps a resource to a domain name. For example, a standard query +might bind a domain name to a host address; the corresponding inverse +query binds the host address to a domain name. + +Inverse queries take the form of a single RR in the answer section of +the message, with an empty question section. The owner name of the +query RR and its TTL are not significant. The response carries +questions in the question section which identify all names possessing +the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows +about all of the domain name space, the response can never be assumed to +be complete. Thus inverse queries are primarily useful for database +management and debugging activities. Inverse queries are NOT an +acceptable method of mapping host addresses to host names; use the IN- +ADDR.ARPA domain instead. + +Where possible, name servers should provide case-insensitive comparisons +for inverse queries. Thus an inverse query asking for an MX RR of +"Venera.isi.edu" should get the same response as a query for +"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should +produce the same result as an inverse query for "IBM-pc unix". However, +this cannot be guaranteed because name servers may possess RRs that +contain character strings but the name server does not know that the +data is character. + +When a name server processes an inverse query, it either returns: + + 1. zero, one, or multiple domain names for the specified + resource as QNAMEs in the question section + + + +Mockapetris [Page 40] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 2. an error code indicating that the name server doesn't support + inverse mapping of the specified resource type. + +When the response to an inverse query contains one or more QNAMEs, the +owner name and TTL of the RR in the answer section which defines the +inverse query is modified to exactly match an RR found at the first +QNAME. + +RRs returned in the inverse queries cannot be cached using the same +mechanism as is used for the replies to standard queries. One reason +for this is that a name might have multiple RRs of the same type, and +only one would appear. For example, an inverse query for a single +address of a multiply homed host might create the impression that only +one address existed. + +6.4.2. Inverse query and response example The overall structure +of an inverse query for retrieving the domain name that corresponds to +Internet address 10.1.0.52 is shown below: + + +-----------------------------------------+ + Header | OPCODE=IQUERY, ID=997 | + +-----------------------------------------+ + Question | <empty> | + +-----------------------------------------+ + Answer | <anyname> A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +This query asks for a question whose answer is the Internet style +address 10.1.0.52. Since the owner name is not known, any domain name +can be used as a placeholder (and is ignored). A single octet of zero, +signifying the root, is usually used because it minimizes the length of +the message. The TTL of the RR is not significant. The response to +this query might be: + + + + + + + + + + + + + + +Mockapetris [Page 41] + +RFC 1035 Domain Implementation and Specification November 1987 + + + +-----------------------------------------+ + Header | OPCODE=RESPONSE, ID=997 | + +-----------------------------------------+ + Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU | + +-----------------------------------------+ + Answer | VENERA.ISI.EDU A IN 10.1.0.52 | + +-----------------------------------------+ + Authority | <empty> | + +-----------------------------------------+ + Additional | <empty> | + +-----------------------------------------+ + +Note that the QTYPE in a response to an inverse query is the same as the +TYPE field in the answer section of the inverse query. Responses to +inverse queries may contain multiple questions when the inverse is not +unique. If the question section in the response is not empty, then the +RR in the answer section is modified to correspond to be an exact copy +of an RR at the first QNAME. + +6.4.3. Inverse query processing + +Name servers that support inverse queries can support these operations +through exhaustive searches of their databases, but this becomes +impractical as the size of the database increases. An alternative +approach is to invert the database according to the search key. + +For name servers that support multiple zones and a large amount of data, +the recommended approach is separate inversions for each zone. When a +particular zone is changed during a refresh, only its inversions need to +be redone. + +Support for transfer of this type of inversion may be included in future +versions of the domain system, but is not supported in this version. + +6.5. Completion queries and responses + +The optional completion services described in RFC-882 and RFC-883 have +been deleted. Redesigned services may become available in the future. + + + + + + + + + + + + + +Mockapetris [Page 42] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7. RESOLVER IMPLEMENTATION + +The top levels of the recommended resolver algorithm are discussed in +[RFC-1034]. This section discusses implementation details assuming the +database structure suggested in the name server implementation section +of this memo. + +7.1. Transforming a user request into a query + +The first step a resolver takes is to transform the client's request, +stated in a format suitable to the local OS, into a search specification +for RRs at a specific name which match a specific QTYPE and QCLASS. +Where possible, the QTYPE and QCLASS should correspond to a single type +and a single class, because this makes the use of cached data much +simpler. The reason for this is that the presence of data of one type +in a cache doesn't confirm the existence or non-existence of data of +other types, hence the only way to be sure is to consult an +authoritative source. If QCLASS=* is used, then authoritative answers +won't be available. + +Since a resolver must be able to multiplex multiple requests if it is to +perform its function efficiently, each pending request is usually +represented in some block of state information. This state block will +typically contain: + + - A timestamp indicating the time the request began. + The timestamp is used to decide whether RRs in the database + can be used or are out of date. This timestamp uses the + absolute time format previously discussed for RR storage in + zones and caches. Note that when an RRs TTL indicates a + relative time, the RR must be timely, since it is part of a + zone. When the RR has an absolute time, it is part of a + cache, and the TTL of the RR is compared against the timestamp + for the start of the request. + + Note that using the timestamp is superior to using a current + time, since it allows RRs with TTLs of zero to be entered in + the cache in the usual manner, but still used by the current + request, even after intervals of many seconds due to system + load, query retransmission timeouts, etc. + + - Some sort of parameters to limit the amount of work which will + be performed for this request. + + The amount of work which a resolver will do in response to a + client request must be limited to guard against errors in the + database, such as circular CNAME references, and operational + problems, such as network partition which prevents the + + + +Mockapetris [Page 43] + +RFC 1035 Domain Implementation and Specification November 1987 + + + resolver from accessing the name servers it needs. While + local limits on the number of times a resolver will retransmit + a particular query to a particular name server address are + essential, the resolver should have a global per-request + counter to limit work on a single request. The counter should + be set to some initial value and decremented whenever the + resolver performs any action (retransmission timeout, + retransmission, etc.) If the counter passes zero, the request + is terminated with a temporary error. + + Note that if the resolver structure allows one request to + start others in parallel, such as when the need to access a + name server for one request causes a parallel resolve for the + name server's addresses, the spawned request should be started + with a lower counter. This prevents circular references in + the database from starting a chain reaction of resolver + activity. + + - The SLIST data structure discussed in [RFC-1034]. + + This structure keeps track of the state of a request if it + must wait for answers from foreign name servers. + +7.2. Sending the queries + +As described in [RFC-1034], the basic task of the resolver is to +formulate a query which will answer the client's request and direct that +query to name servers which can provide the information. The resolver +will usually only have very strong hints about which servers to ask, in +the form of NS RRs, and may have to revise the query, in response to +CNAMEs, or revise the set of name servers the resolver is asking, in +response to delegation responses which point the resolver to name +servers closer to the desired information. In addition to the +information requested by the client, the resolver may have to call upon +its own services to determine the address of name servers it wishes to +contact. + +In any case, the model used in this memo assumes that the resolver is +multiplexing attention between multiple requests, some from the client, +and some internally generated. Each request is represented by some +state information, and the desired behavior is that the resolver +transmit queries to name servers in a way that maximizes the probability +that the request is answered, minimizes the time that the request takes, +and avoids excessive transmissions. The key algorithm uses the state +information of the request to select the next name server address to +query, and also computes a timeout which will cause the next action +should a response not arrive. The next action will usually be a +transmission to some other server, but may be a temporary error to the + + + +Mockapetris [Page 44] + +RFC 1035 Domain Implementation and Specification November 1987 + + +client. + +The resolver always starts with a list of server names to query (SLIST). +This list will be all NS RRs which correspond to the nearest ancestor +zone that the resolver knows about. To avoid startup problems, the +resolver should have a set of default servers which it will ask should +it have no current NS RRs which are appropriate. The resolver then adds +to SLIST all of the known addresses for the name servers, and may start +parallel requests to acquire the addresses of the servers when the +resolver has the name, but no addresses, for the name servers. + +To complete initialization of SLIST, the resolver attaches whatever +history information it has to the each address in SLIST. This will +usually consist of some sort of weighted averages for the response time +of the address, and the batting average of the address (i.e., how often +the address responded at all to the request). Note that this +information should be kept on a per address basis, rather than on a per +name server basis, because the response time and batting average of a +particular server may vary considerably from address to address. Note +also that this information is actually specific to a resolver address / +server address pair, so a resolver with multiple addresses may wish to +keep separate histories for each of its addresses. Part of this step +must deal with addresses which have no such history; in this case an +expected round trip time of 5-10 seconds should be the worst case, with +lower estimates for the same local network, etc. + +Note that whenever a delegation is followed, the resolver algorithm +reinitializes SLIST. + +The information establishes a partial ranking of the available name +server addresses. Each time an address is chosen and the state should +be altered to prevent its selection again until all other addresses have +been tried. The timeout for each transmission should be 50-100% greater +than the average predicted value to allow for variance in response. + +Some fine points: + + - The resolver may encounter a situation where no addresses are + available for any of the name servers named in SLIST, and + where the servers in the list are precisely those which would + normally be used to look up their own addresses. This + situation typically occurs when the glue address RRs have a + smaller TTL than the NS RRs marking delegation, or when the + resolver caches the result of a NS search. The resolver + should detect this condition and restart the search at the + next ancestor zone, or alternatively at the root. + + + + + +Mockapetris [Page 45] + +RFC 1035 Domain Implementation and Specification November 1987 + + + - If a resolver gets a server error or other bizarre response + from a name server, it should remove it from SLIST, and may + wish to schedule an immediate transmission to the next + candidate server address. + +7.3. Processing responses + +The first step in processing arriving response datagrams is to parse the +response. This procedure should include: + + - Check the header for reasonableness. Discard datagrams which + are queries when responses are expected. + + - Parse the sections of the message, and insure that all RRs are + correctly formatted. + + - As an optional step, check the TTLs of arriving data looking + for RRs with excessively long TTLs. If a RR has an + excessively long TTL, say greater than 1 week, either discard + the whole response, or limit all TTLs in the response to 1 + week. + +The next step is to match the response to a current resolver request. +The recommended strategy is to do a preliminary matching using the ID +field in the domain header, and then to verify that the question section +corresponds to the information currently desired. This requires that +the transmission algorithm devote several bits of the domain ID field to +a request identifier of some sort. This step has several fine points: + + - Some name servers send their responses from different + addresses than the one used to receive the query. That is, a + resolver cannot rely that a response will come from the same + address which it sent the corresponding query to. This name + server bug is typically encountered in UNIX systems. + + - If the resolver retransmits a particular request to a name + server it should be able to use a response from any of the + transmissions. However, if it is using the response to sample + the round trip time to access the name server, it must be able + to determine which transmission matches the response (and keep + transmission times for each outgoing message), or only + calculate round trip times based on initial transmissions. + + - A name server will occasionally not have a current copy of a + zone which it should have according to some NS RRs. The + resolver should simply remove the name server from the current + SLIST, and continue. + + + + +Mockapetris [Page 46] + +RFC 1035 Domain Implementation and Specification November 1987 + + +7.4. Using the cache + +In general, we expect a resolver to cache all data which it receives in +responses since it may be useful in answering future client requests. +However, there are several types of data which should not be cached: + + - When several RRs of the same type are available for a + particular owner name, the resolver should either cache them + all or none at all. When a response is truncated, and a + resolver doesn't know whether it has a complete set, it should + not cache a possibly partial set of RRs. + + - Cached data should never be used in preference to + authoritative data, so if caching would cause this to happen + the data should not be cached. + + - The results of an inverse query should not be cached. + + - The results of standard queries where the QNAME contains "*" + labels if the data might be used to construct wildcards. The + reason is that the cache does not necessarily contain existing + RRs or zone boundary information which is necessary to + restrict the application of the wildcard RRs. + + - RR data in responses of dubious reliability. When a resolver + receives unsolicited responses or RR data other than that + requested, it should discard it without caching it. The basic + implication is that all sanity checks on a packet should be + performed before any of it is cached. + +In a similar vein, when a resolver has a set of RRs for some name in a +response, and wants to cache the RRs, it should check its cache for +already existing RRs. Depending on the circumstances, either the data +in the response or the cache is preferred, but the two should never be +combined. If the data in the response is from authoritative data in the +answer section, it is always preferred. + +8. MAIL SUPPORT + +The domain system defines a standard for mapping mailboxes into domain +names, and two methods for using the mailbox information to derive mail +routing information. The first method is called mail exchange binding +and the other method is mailbox binding. The mailbox encoding standard +and mail exchange binding are part of the DNS official protocol, and are +the recommended method for mail routing in the Internet. Mailbox +binding is an experimental feature which is still under development and +subject to change. + + + + +Mockapetris [Page 47] + +RFC 1035 Domain Implementation and Specification November 1987 + + +The mailbox encoding standard assumes a mailbox name of the form +"<local-part>@<mail-domain>". While the syntax allowed in each of these +sections varies substantially between the various mail internets, the +preferred syntax for the ARPA Internet is given in [RFC-822]. + +The DNS encodes the <local-part> as a single label, and encodes the +<mail-domain> as a domain name. The single label from the <local-part> +is prefaced to the domain name from <mail-domain> to form the domain +name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI- +NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the +<local-part> contains dots or other special characters, its +representation in a master file will require the use of backslash +quoting to ensure that the domain name is properly encoded. For +example, the mailbox Action.domains@ISI.EDU would be represented as +Action\.domains.ISI.EDU. + +8.1. Mail exchange binding + +Mail exchange binding uses the <mail-domain> part of a mailbox +specification to determine where mail should be sent. The <local-part> +is not even consulted. [RFC-974] specifies this method in detail, and +should be consulted before attempting to use mail exchange support. + +One of the advantages of this method is that it decouples mail +destination naming from the hosts used to support mail service, at the +cost of another layer of indirection in the lookup function. However, +the addition layer should eliminate the need for complicated "%", "!", +etc encodings in <local-part>. + +The essence of the method is that the <mail-domain> is used as a domain +name to locate type MX RRs which list hosts willing to accept mail for +<mail-domain>, together with preference values which rank the hosts +according to an order specified by the administrators for <mail-domain>. + +In this memo, the <mail-domain> ISI.EDU is used in examples, together +with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for +ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would +route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name +VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host +addresses. + +8.2. Mailbox binding (Experimental) + +In mailbox binding, the mailer uses the entire mail destination +specification to construct a domain name. The encoded domain name for +the mailbox is used as the QNAME field in a QTYPE=MAILB query. + +Several outcomes are possible for this query: + + + +Mockapetris [Page 48] + +RFC 1035 Domain Implementation and Specification November 1987 + + + 1. The query can return a name error indicating that the mailbox + does not exist as a domain name. + + In the long term, this would indicate that the specified + mailbox doesn't exist. However, until the use of mailbox + binding is universal, this error condition should be + interpreted to mean that the organization identified by the + global part does not support mailbox binding. The + appropriate procedure is to revert to exchange binding at + this point. + + 2. The query can return a Mail Rename (MR) RR. + + The MR RR carries new mailbox specification in its RDATA + field. The mailer should replace the old mailbox with the + new one and retry the operation. + + 3. The query can return a MB RR. + + The MB RR carries a domain name for a host in its RDATA + field. The mailer should deliver the message to that host + via whatever protocol is applicable, e.g., b,SMTP. + + 4. The query can return one or more Mail Group (MG) RRs. + + This condition means that the mailbox was actually a mailing + list or mail group, rather than a single mailbox. Each MG RR + has a RDATA field that identifies a mailbox that is a member + of the group. The mailer should deliver a copy of the + message to each member. + + 5. The query can return a MB RR as well as one or more MG RRs. + + This condition means the the mailbox was actually a mailing + list. The mailer can either deliver the message to the host + specified by the MB RR, which will in turn do the delivery to + all members, or the mailer can use the MG RRs to do the + expansion itself. + +In any of these cases, the response may include a Mail Information +(MINFO) RR. This RR is usually associated with a mail group, but is +legal with a MB. The MINFO RR identifies two mailboxes. One of these +identifies a responsible person for the original mailbox name. This +mailbox should be used for requests to be added to a mail group, etc. +The second mailbox name in the MINFO RR identifies a mailbox that should +receive error messages for mail failures. This is particularly +appropriate for mailing lists when errors in member names should be +reported to a person other than the one who sends a message to the list. + + + +Mockapetris [Page 49] + +RFC 1035 Domain Implementation and Specification November 1987 + + +New fields may be added to this RR in the future. + + +9. REFERENCES and BIBLIOGRAPHY + +[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena + Technical Plan - Name Service, April 1987, version 1.9. + + Describes the fundamentals of the Hesiod name service. + +[IEN-116] J. Postel, "Internet Name Server", IEN-116, + USC/Information Sciences Institute, August 1979. + + A name service obsoleted by the Domain Name System, but + still in use. + +[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks", + Communications of the ACM, October 1986, volume 29, number + 10. + +[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network + Information Center, SRI International, December 1977. + +[RFC-768] J. Postel, "User Datagram Protocol", RFC-768, + USC/Information Sciences Institute, August 1980. + +[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793, + USC/Information Sciences Institute, September 1981. + +[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT, + September 1981. + + Suggests introduction of a hierarchy in place of a flat + name space for the Internet. + +[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805, + USC/Information Sciences Institute, February 1982. + +[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD + Internet Host Table Specification", RFC-810, Network + Information Center, SRI International, March 1982. + + Obsolete. See RFC-952. + +[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames + Server", RFC-811, Network Information Center, SRI + International, March 1982. + + + + +Mockapetris [Page 50] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Obsolete. See RFC-953. + +[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812, + Network Information Center, SRI International, March + 1982. + +[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for + Internet User Applications", RFC-819, Network + Information Center, SRI International, August 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821, + USC/Information Sciences Institute, August 1980. + +[RFC-830] Z. Su, "A Distributed System for Internet Name Service", + RFC-830, Network Information Center, SRI International, + October 1982. + + Early thoughts on the design of the domain system. + Current implementation is completely different. + +[RFC-882] P. Mockapetris, "Domain names - Concepts and + Facilities," RFC-882, USC/Information Sciences + Institute, November 1983. + + Superseded by this memo. + +[RFC-883] P. Mockapetris, "Domain names - Implementation and + Specification," RFC-883, USC/Information Sciences + Institute, November 1983. + + Superseded by this memo. + +[RFC-920] J. Postel and J. Reynolds, "Domain Requirements", + RFC-920, USC/Information Sciences Institute, + October 1984. + + Explains the naming scheme for top level domains. + +[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host + Table Specification", RFC-952, SRI, October 1985. + + Specifies the format of HOSTS.TXT, the host/address + table replaced by the DNS. + + + + + +Mockapetris [Page 51] + +RFC 1035 Domain Implementation and Specification November 1987 + + +[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server", + RFC-953, SRI, October 1985. + + This RFC contains the official specification of the + hostname server protocol, which is obsoleted by the DNS. + This TCP based protocol accesses information stored in + the RFC-952 format, and is used to obtain copies of the + host table. + +[RFC-973] P. Mockapetris, "Domain System Changes and + Observations", RFC-973, USC/Information Sciences + Institute, January 1986. + + Describes changes to RFC-882 and RFC-883 and reasons for + them. + +[RFC-974] C. Partridge, "Mail routing and the domain system", + RFC-974, CSNET CIC BBN Labs, January 1986. + + Describes the transition from HOSTS.TXT based mail + addressing to the more powerful MX system used with the + domain system. + +[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Concepts and Methods", + RFC-1001, March 1987. + + This RFC and RFC-1002 are a preliminary design for + NETBIOS on top of TCP/IP which proposes to base NetBIOS + name service on top of the DNS. + +[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS + service on a TCP/UDP transport: Detailed + Specifications", RFC-1002, March 1987. + +[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010, + USC/Information Sciences Institute, May 1987. + + Contains socket numbers and mnemonics for host names, + operating systems, etc. + +[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031, + November 1987. + + Describes a plan for converting the MILNET to the DNS. + +[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for + Administrators", RFC-1032, November 1987. + + + +Mockapetris [Page 52] + +RFC 1035 Domain Implementation and Specification November 1987 + + + Describes the registration policies used by the NIC to + administer the top level domains and delegate subzones. + +[RFC-1033] M. Lottor, "Domain Administrators Operations Guide", + RFC-1033, November 1987. + + A cookbook for domain administrators. + +[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET + Name Server", Computer Networks, vol 6, nr 3, July 1982. + + Describes a name service for CSNET which is independent + from the DNS and DNS use in the CSNET. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 53] + +RFC 1035 Domain Implementation and Specification November 1987 + + +Index + + * 13 + + ; 33, 35 + + <character-string> 35 + <domain-name> 34 + + @ 35 + + \ 35 + + A 12 + + Byte order 8 + + CH 13 + Character case 9 + CLASS 11 + CNAME 12 + Completion 42 + CS 13 + + Hesiod 13 + HINFO 12 + HS 13 + + IN 13 + IN-ADDR.ARPA domain 22 + Inverse queries 40 + + Mailbox names 47 + MB 12 + MD 12 + MF 12 + MG 12 + MINFO 12 + MINIMUM 20 + MR 12 + MX 12 + + NS 12 + NULL 12 + + Port numbers 32 + Primary server 5 + PTR 12, 18 + + + +Mockapetris [Page 54] + +RFC 1035 Domain Implementation and Specification November 1987 + + + QCLASS 13 + QTYPE 12 + + RDATA 12 + RDLENGTH 11 + + Secondary server 5 + SOA 12 + Stub resolvers 7 + + TCP 32 + TXT 12 + TYPE 11 + + UDP 32 + + WKS 12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Mockapetris [Page 55] + diff --git a/tests/dns/testdata/dstrandom/random.data b/tests/dns/testdata/dstrandom/random.data Binary files differnew file mode 100644 index 0000000..354add0 --- /dev/null +++ b/tests/dns/testdata/dstrandom/random.data diff --git a/tests/dns/testdata/master/master1.data b/tests/dns/testdata/master/master1.data new file mode 100644 index 0000000..030bc68 --- /dev/null +++ b/tests/dns/testdata/master/master1.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/master/master10.data b/tests/dns/testdata/master/master10.data new file mode 100644 index 0000000..9ee052f --- /dev/null +++ b/tests/dns/testdata/master/master10.data @@ -0,0 +1,7 @@ +; +; the following black line contains spaces + +; +@ 300 IN A 10.0.0.1 + ; +; diff --git a/tests/dns/testdata/master/master11.data b/tests/dns/testdata/master/master11.data new file mode 100644 index 0000000..0aaec25 --- /dev/null +++ b/tests/dns/testdata/master/master11.data @@ -0,0 +1,6 @@ +; +; The following serial number contains a leading 0 and a 9 so the +; we can catch cases where it is incorrectly treated as a octal +; number. +; +@ 300 IN SOA ns hostmaster 00090000 1200 3600 604800 300 diff --git a/tests/dns/testdata/master/master12.data.in b/tests/dns/testdata/master/master12.data.in new file mode 100644 index 0000000..3634388 --- /dev/null +++ b/tests/dns/testdata/master/master12.data.in @@ -0,0 +1 @@ +00000002000000004ed7306600000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/tests/dns/testdata/master/master13.data.in b/tests/dns/testdata/master/master13.data.in new file mode 100644 index 0000000..d1c262f --- /dev/null +++ b/tests/dns/testdata/master/master13.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f00000000000000000000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/tests/dns/testdata/master/master14.data.in b/tests/dns/testdata/master/master14.data.in new file mode 100644 index 0000000..149a25f --- /dev/null +++ b/tests/dns/testdata/master/master14.data.in @@ -0,0 +1 @@ +00000002000000014ed7337f0000000277df41e50000000000000051000100060000000003e80000000100060474657374000035096c6f63616c686f7374000a706f73746d6173746572096c6f63616c686f73740076cb8ab100000e100000070800093a8000000e1000000046000100020000000003e8000000030006047465737400000c026e730376697803636f6d00000d036e73320376697803636f6d00000d036e73330376697803636f6d0000000022000100010000000003e80000000100080162047465737400000401020304 diff --git a/tests/dns/testdata/master/master15.data b/tests/dns/testdata/master/master15.data new file mode 100644 index 0000000..cf413ce --- /dev/null +++ b/tests/dns/testdata/master/master15.data @@ -0,0 +1,1609 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 +c in txt ( TOOBIGTOOBIGTOOBIGTOOBIGTOOBIGTOOBI + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 ) diff --git a/tests/dns/testdata/master/master16.data b/tests/dns/testdata/master/master16.data new file mode 100644 index 0000000..e969bd3 --- /dev/null +++ b/tests/dns/testdata/master/master16.data @@ -0,0 +1,1609 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +b in a 1.2.3.4 +c in txt ( MAXSIZSEMAXSIZSEMAXSIZSEMAXSIZSMAX + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 + 1234567890123456789012345678901234567890 ) diff --git a/tests/dns/testdata/master/master17.data b/tests/dns/testdata/master/master17.data new file mode 100644 index 0000000..4b2b63d --- /dev/null +++ b/tests/dns/testdata/master/master17.data @@ -0,0 +1,14 @@ +$ORIGIN test. +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.test. + in ns ns2.test. + in ns ns3.test. +b in a 1.2.3.4 +$ORIGIN sub.test. + in a 4.3.2.1 diff --git a/tests/dns/testdata/master/master18.data.in b/tests/dns/testdata/master/master18.data.in new file mode 100644 index 0000000..73c17ff --- /dev/null +++ b/tests/dns/testdata/master/master18.data.in @@ -0,0 +1,10 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +$INCLUDE "@TOP_SRCDIR@/testkeys/Kexample.+008+20386.key"; +$INCLUDE "@TOP_SRCDIR@/testkeys/Kexample.+008+37464.key"; diff --git a/tests/dns/testdata/master/master2.data b/tests/dns/testdata/master/master2.data new file mode 100644 index 0000000..b8ca38d --- /dev/null +++ b/tests/dns/testdata/master/master2.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/master/master3.data b/tests/dns/testdata/master/master3.data new file mode 100644 index 0000000..7283af6 --- /dev/null +++ b/tests/dns/testdata/master/master3.data @@ -0,0 +1,11 @@ +$TTL 1000 + in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com + in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/master/master4.data b/tests/dns/testdata/master/master4.data new file mode 100644 index 0000000..3a694ea --- /dev/null +++ b/tests/dns/testdata/master/master4.data @@ -0,0 +1,11 @@ + +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a in ns ns.vix.com. +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/master/master5.data b/tests/dns/testdata/master/master5.data new file mode 100644 index 0000000..95234bd --- /dev/null +++ b/tests/dns/testdata/master/master5.data @@ -0,0 +1,11 @@ +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum +a any ns ns.vix.com. +a in ns ns2vix.com. +a in ns ns3vix.com. +b in a 1.2.3.4 diff --git a/tests/dns/testdata/master/master6.data b/tests/dns/testdata/master/master6.data new file mode 100644 index 0000000..a9a37bb --- /dev/null +++ b/tests/dns/testdata/master/master6.data @@ -0,0 +1,33 @@ + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +secure1 3600 IN DNSKEY ( + FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15 + 3 3 + ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2 + 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n + 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql + sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY + AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12 + pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV + /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1 + oFq/TNZlSe+N ) + +secure2 3600 in DNSKEY ( + flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15 + 3 3 + ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2 + 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n + 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql + sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY + AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12 + pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV + /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1 + oFq/TNZlSe+N ) + diff --git a/tests/dns/testdata/master/master7.data b/tests/dns/testdata/master/master7.data new file mode 100644 index 0000000..2638b5d --- /dev/null +++ b/tests/dns/testdata/master/master7.data @@ -0,0 +1,17 @@ + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + +secure1 3600 IN DNSKEY ( + NOKEY|FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15 + 3 3 ) + +secure2 3600 in DNSKEY ( + nokey|flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15 + 3 3 ) + diff --git a/tests/dns/testdata/master/master8.data b/tests/dns/testdata/master/master8.data new file mode 100644 index 0000000..d16b6f3 --- /dev/null +++ b/tests/dns/testdata/master/master8.data @@ -0,0 +1,4 @@ +; +; master6.data contains a good zone file +; +$include testdata/master/master6.data diff --git a/tests/dns/testdata/master/master9.data b/tests/dns/testdata/master/master9.data new file mode 100644 index 0000000..b22688b --- /dev/null +++ b/tests/dns/testdata/master/master9.data @@ -0,0 +1,4 @@ +; +; master5.data is bad +; +$include testdata/master/master5.data diff --git a/tests/dns/testdata/nsec3/1024.db b/tests/dns/testdata/nsec3/1024.db new file mode 100644 index 0000000..2576328 --- /dev/null +++ b/tests/dns/testdata/nsec3/1024.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 1024 bit key. +test. IN DNSKEY 256 3 5 AwEAAd5oKx06HRE6NRrTDz49lljdRmxgp/4YB/cyMkpwUMkaLhDNCfTq hql84ab2LRbtUWLHFXGWENvxPGQzVHeleXu+3ThNfFOwIaySedxHmLGT lTtBRDhPc8iSb+2IYDemmA+ut8kwHhCVz/tDMbD/dgAswdOtmXCpQyJk Q1HqY3Xj diff --git a/tests/dns/testdata/nsec3/2048.db b/tests/dns/testdata/nsec3/2048.db new file mode 100644 index 0000000..26dd980 --- /dev/null +++ b/tests/dns/testdata/nsec3/2048.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= diff --git a/tests/dns/testdata/nsec3/4096.db b/tests/dns/testdata/nsec3/4096.db new file mode 100644 index 0000000..d628c33 --- /dev/null +++ b/tests/dns/testdata/nsec3/4096.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/tests/dns/testdata/nsec3/min-1024.db b/tests/dns/testdata/nsec3/min-1024.db new file mode 100644 index 0000000..360c282 --- /dev/null +++ b/tests/dns/testdata/nsec3/min-1024.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 1024 bit key. +test. IN DNSKEY 256 3 5 AwEAAd5oKx06HRE6NRrTDz49lljdRmxgp/4YB/cyMkpwUMkaLhDNCfTq hql84ab2LRbtUWLHFXGWENvxPGQzVHeleXu+3ThNfFOwIaySedxHmLGT lTtBRDhPc8iSb+2IYDemmA+ut8kwHhCVz/tDMbD/dgAswdOtmXCpQyJk Q1HqY3Xj +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/tests/dns/testdata/nsec3/min-2048.db b/tests/dns/testdata/nsec3/min-2048.db new file mode 100644 index 0000000..606264e --- /dev/null +++ b/tests/dns/testdata/nsec3/min-2048.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +test. SOA . . 0 0 0 0 0 +test. NS . +; 2048 bits +test. IN DNSKEY 256 3 5 AwEAAcfQX59iZr9gK+XzhTZQ5KWrfCLA0iYHTqheEIhC2dXS8gUSppQS g9SmzH2129u/LSSb7gqJSoLLAsn36iinqCqUXl2BT6xzwznbSP3mn0hn N6DegsykcYhHycKH6ifjZiMN+SGGeNsi5rhoW5Cj9ptw3C3yQnrFNDbS GZCT97z5lpQU3ZcvP4RDNk7dhri7Bh3SJeaCFoqx00NgFvlBR48hosSG bGUbUKzNf58GBTkW4Us2jIWsreZx8LLLev232Hy7NU9L19k+hVq7pJOf Uvtrn5fmGSutWOzsR+8EacOnh0lwssCKjutk5MSmfdFC5P7CTZkdq58L 8he13HGmr00= +; 4096 bits +test. IN DNSKEY 256 3 5 AwEAAbYlqbKxXoq9mzkqdsAaSZ3XywBVAb2sCTgrQBCExyGEYNpWw3LN +imCrLQi7jHKQW6GZIqKNgQaiFEwr3zK8nPWbwNwyKU9a2hhINv/gim1 5iA87Vu7DiiJrQ0O79ospvsGsKknBQ41zaaQMp3Q/W1S6WNe4uyh4C/f R0qmxT+8MyXEqCpTGb+e+YT6BuqpNQPuYYYvUJ1/HJltzY/lY2b9RZ+Q ZJ23Zje79YIRM0kJapqj11fDUDeynhDL1DUikYCwRfQiO/blChhOHjIa uTK1qqRY3fqanLGOufpLTr7GRpL7RxeRIMJfDzmcjFLmCsMA1AJ56Bxq jiXr3ODgn9D30vAB74Lr7lqLQSWyrSlJjoZLLhmPrEP/nnuCxEhOhDRA XJpJWpcQ4Hdu+yb5K/qldnsGLLI1Hr0GmhLTDHsxDb6BxM7/8rv8QeQY GKSGshBqD2lO1xUVT8inbi8uXI1iyN68vHX6xoFT5wsjls70PxSZPO5i F40vn6BWNsHtKWOCDqMKYx8hYwiv0zETVwxBaj58vylFwYGU+g1wIQmF Pgi2HKv4KaxgikUvdFISre5rxVoG5VrmmXWiNJcLTbwZ+tE1xujCNU1c V31CaIB5hdSnkEvQADr5V64RTxWAKuSLNMU+XUqTkaJHasSm3OPJOteo SPj2uoesuxNFYps3 diff --git a/tests/dns/testdata/nsec3param/nsec3.db.signed b/tests/dns/testdata/nsec3param/nsec3.db.signed new file mode 100644 index 0000000..aeced0e --- /dev/null +++ b/tests/dns/testdata/nsec3param/nsec3.db.signed @@ -0,0 +1,73 @@ +; File written on Mon Nov 16 16:04:21 2020 +; dnssec_signzone version 9.16.8 +nsec3. 1000 IN SOA nsec3. postmaster.nsec3. ( + 1993050801 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 minutes) + 604800 ; expire (1 week) + 3600 ; minimum (1 hour) + ) + 1000 RRSIG SOA 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + qh61ZPgQaNLAoIQvAoTLbR3sLBY7XATaMGSS + fYOssQWvgAzpAzhalmF/cSXmQ/RZQOyIdpVg + v3rgyTxA2vGNnA== ) + 1000 NS ns1.nsec3. + 1000 NS ns2.nsec3. + 1000 RRSIG NS 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + 4Le+e5Lu/taEvrvrmBn/z+QP4zhzUqwO6v70 + WYrzCggUls8+fUd2unBHDPWag1oSKfNpGGWA + crihrs4RhMPfZA== ) + 1000 DNSKEY 257 3 13 ( + VKkttSi/v3lAyzUYnykwdwowXfDOQ7wdN9BT + +eb8fVfgRApvuun9hjUBlv7ogriU/GAb60B8 + juj9bXZADT+OGg== + ) ; KSK; alg = ECDSAP256SHA256 ; key id = 40382 + 1000 RRSIG DNSKEY 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + ZnBqGgWvHwjjQBSIRPXe2fx6+MsQp1QQdzJ0 + QaEyaOmud5JPatUXaV9eFRcPNCsi+2HZSZVp + vsAGUCge7w6u9A== ) + 0 NSEC3PARAM 1 0 5 FEDCBA98 + 0 RRSIG NSEC3PARAM 13 1 0 ( + 20201216140421 20201116140421 40382 nsec3. + WPTD+5vr54YtvGqCUJHPvGdF7Wd4piZYltcs + cztBRfdM7FRJ/zvrDS72rt6zm0TYSXzawqt/ + MiwOkYKv2vxfUg== ) +ns2.nsec3. 1000 IN A 1.2.3.5 + 1000 RRSIG A 13 2 1000 ( + 20201216140421 20201116140421 40382 nsec3. + l9Mc2Y5JFmllSxJj3GUdH6RtEsYfhjJU39sa + vAVa4zxv6S9vU+vLvTA05aQ+DPLvKTX+WNH7 + dDa+Yy5ffBs68g== ) +QVCH33BSJ0Q2C74FEDFDBCFQHO255NEB.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + STH5N5QDVC5DGEN5VGUC7JGALSM3R8AP + A RRSIG ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + F/wKQtv+RlBHG1WCz0CkHlTSoUiRx0z+qBI1 + GTHoXSjgG1NSHqTI4C32AasZSMp+uuF2R8KW + 9z4gOLucl0Xmfg== ) +STH5N5QDVC5DGEN5VGUC7JGALSM3R8AP.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + A084TNR6VJ2ND5K1U0AI4HO4EPVKBG4U + NS SOA RRSIG DNSKEY NSEC3PARAM ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + 9TgGFGY3vwkxMFlXy3oKMgHPqvcPozKDHZzc + Ny6eJn3TXNX5bLhiT5rw5+CCtyOEQmn3pf0X + njK7jZBAcBV+5Q== ) +A084TNR6VJ2ND5K1U0AI4HO4EPVKBG4U.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + QVCH33BSJ0Q2C74FEDFDBCFQHO255NEB + A RRSIG ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + auf+5lrkMESIfdFK8bf4yg1a+NLGWzgUmohS + ydcKaJz0XcnULegatWdfE75jmZoDeqKNpwdL + 5lQ77GF4cEh1OQ== ) +ns1.nsec3. 1000 IN A 1.2.3.4 + 1000 RRSIG A 13 2 1000 ( + 20201216140421 20201116140421 40382 nsec3. + yAmr1EE8qe+Jl+wQXOdj/uSjMFUmns0D1lx6 + zAVe9BaQwvF3wR7ZUk/u9G0RrUBchmEj0+yq + KEsw32Tru4Romg== ) diff --git a/tests/dns/testdata/zt/zone1.db b/tests/dns/testdata/zt/zone1.db new file mode 100644 index 0000000..85e7951 --- /dev/null +++ b/tests/dns/testdata/zt/zone1.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.vix.com. + in ns ns2.vix.com. + in ns ns3.vix.com. +a in a 1.2.3.4 diff --git a/tests/dns/testkeys/Kexample.+008+20386.key b/tests/dns/testkeys/Kexample.+008+20386.key new file mode 100644 index 0000000..3404dca --- /dev/null +++ b/tests/dns/testkeys/Kexample.+008+20386.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 20386, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 257 3 8 AwEAAZd7/hBRvMooz0sepkD/2r3Bp021f8lGzDj6sZEVbg1hcqZTzURc eGkS541wyOqjvJv2KBi5qLLE2HthmexmOBycjTQ7EiKd1P9bE8RgF8Et j73X/CHLiX6YL7cb93TXWiUvbRh4E6D2URgOmxMdMOXTuCvjvDaGVCOt Jc77UUosuBeurZzP8g8t/zccAUTzu2cdRyI5/ZxOBfJaDtc9TlRdWsaN Af+nT0C14ccH7QVlKjjaYV4lXueruDW3yTTzu9bQ1ikgegsCLi/tcD/1 dWTOI9whV06szs+ouhuJkZuhIjrGDtOHCpjPjIxOOrIZceU1YSY30kAR QNVzshJqyx8= diff --git a/tests/dns/testkeys/Kexample.+008+20386.private b/tests/dns/testkeys/Kexample.+008+20386.private new file mode 100644 index 0000000..d8cff93 --- /dev/null +++ b/tests/dns/testkeys/Kexample.+008+20386.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: l3v+EFG8yijPSx6mQP/avcGnTbV/yUbMOPqxkRVuDWFyplPNRFx4aRLnjXDI6qO8m/YoGLmossTYe2GZ7GY4HJyNNDsSIp3U/1sTxGAXwS2Pvdf8IcuJfpgvtxv3dNdaJS9tGHgToPZRGA6bEx0w5dO4K+O8NoZUI60lzvtRSiy4F66tnM/yDy3/NxwBRPO7Zx1HIjn9nE4F8loO1z1OVF1axo0B/6dPQLXhxwftBWUqONphXiVe56u4NbfJNPO71tDWKSB6CwIuL+1wP/V1ZM4j3CFXTqzOz6i6G4mRm6EiOsYO04cKmM+MjE46shlx5TVhJjfSQBFA1XOyEmrLHw== +PublicExponent: AQAB +PrivateExponent: aSkynrGfldfuz/9e+xCjEcg2FMRDCb+UVpnyWv29gJx9sunKPgLTtF3jUVVSpVE1xi+EdmWsry3n+v8uk+YCXhpwDCpV1KItE3huqIzs8LZoaypdZjieIrwTo9JOX1aAxf++hJYXSk60zTaWgRZqs6He4Nkf99oY3wt8i8v8CrkfQy76K/qK9xUVv5GHrEZzCGLfLv77eqDab/J84ANxc0kUtQvgt2/JTHofXmcA6/YDh5PWB8KRw1PjQTck61/xIgfI6ky/yIF1riCQCYXwTv7jcmMV/QvQ+dfN+HZ2CSGp7xcH2Yxe9OhAY823ZkmkOQ2YZPjIj6dEoRMmSiaagQ== +Prime1: x2GMnpRPwvUhM+yPRa7nh5Jjl4mbofeOtVrxe1hEVy8l2UGFh+FDZCbyoLRNUTYDji00NHpGtmcAyoY9pLdOn7ci4zqGVnNJcIY75Ie4p6J7pPfDh9d+AGtJ5NpNhr1sjD0bFncJC2FGY9vj4eC0CkatMu/Qovrd2FwZ8VpDsAk= +Prime2: woB8MYsEfSYGD0hZGtmgK6UQ+Oo9smxdPmahLYXnLSAdqtqZbZX+ABk/kFduT+XwlHOXmp3HMmUtQTRZBaQyBrsFWfWjOGevByEsT9aLQSZOEgnqy4xrc9XNwDs4/WkrEgw/TOVnZYdaCyLxsFl4bpTX8Fj3yVqg/tJvuUMWG+c= +Exponent1: iQO7a9rF+VcVSyZ8yslIaL0r3Z5+Kk8CbhSiMD5XMIbA/sztI5SlCDVPtSpSm8V/qfvcjVeeMokUXRjlUcV6rX1f50F3wf8V79L/Y6v1NJYPXC273CU1fLo+HJv8fOS9rJ3teIGy4HQnuEYLE1WkxA8PxRpSiT3WqHGajmaWb2k= +Exponent2: elMWSI5Wz2KXkwr8Rz+xVWGl7/ZZwRoX9oPTQG8jeiTlo6uBrQMVUPiQGnZyQTuq96JPKYWrXs11DbofdsXSVJtQfUhYU8QZtxEs7jVPNTUjCoNEMKnqdlpz4T8d03pOBTbApNruEVNz1OcwO6m5bUqdGGLLy838zOaKL2i6wec= +Coefficient: q2mejAmT3A4H2C0rT1hm8XQFuISHjAAEyM9t09Q8tEeQ0lHi4gMVA3bXoAn9U21eBkFQDwvyB0vqlVSGgRqHovOKx9uXAU9eoDxGcJsFlGsM0aUsUjGVXv5kVmaw8a5PHBbvYAbgAZUmKqrVF0PWD3o+/DbzP9PCmlJcqxoAulU= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/testkeys/Kexample.+008+37464.key b/tests/dns/testkeys/Kexample.+008+37464.key new file mode 100644 index 0000000..3dd0619 --- /dev/null +++ b/tests/dns/testkeys/Kexample.+008+37464.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 37464, for example. +; Created: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Publish: 20000101000000 (Sat Jan 1 00:00:00 2000) +; Activate: 20000101000000 (Sat Jan 1 00:00:00 2000) +example. IN DNSKEY 256 3 8 AwEAAbxHOF8G0xw9ekCodhL8KivuZ3o0jmGlycLiXBjBN8c5R5fjLjUh D0gy3IDbDC+kLaPhHGF/MwrSEjrgSowxZ8nrxDzsq5ZdpeUsYaNrbQEY /mqf35T/9/Ulm4v06x58v/NTugWd05Xq04aAyfm7EViyGFzmVOVfPnll h9xQtvWEWoRWPseFw+dY5/nc/+xB/IsQMihoH2rO+cek/lsP3R9DsHCG RbQ/ks/+rrp6/O+QJZyZrzsONl7mlMDXNy3Pz9J4qMW2W6Mz702LN324 7/9UsetDGGbuZfrCLMpKWXzdsJm36DOk4aMooS9111plfXaXQgQNcL5G 021utpTau+8= diff --git a/tests/dns/testkeys/Kexample.+008+37464.private b/tests/dns/testkeys/Kexample.+008+37464.private new file mode 100644 index 0000000..ecc2ad0 --- /dev/null +++ b/tests/dns/testkeys/Kexample.+008+37464.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: vEc4XwbTHD16QKh2EvwqK+5nejSOYaXJwuJcGME3xzlHl+MuNSEPSDLcgNsML6Qto+EcYX8zCtISOuBKjDFnyevEPOyrll2l5Sxho2ttARj+ap/flP/39SWbi/TrHny/81O6BZ3TlerThoDJ+bsRWLIYXOZU5V8+eWWH3FC29YRahFY+x4XD51jn+dz/7EH8ixAyKGgfas75x6T+Ww/dH0OwcIZFtD+Sz/6uunr875AlnJmvOw42XuaUwNc3Lc/P0nioxbZbozPvTYs3fbjv/1Sx60MYZu5l+sIsykpZfN2wmbfoM6ThoyihL3XXWmV9dpdCBA1wvkbTbW62lNq77w== +PublicExponent: AQAB +PrivateExponent: AhR3VvVoV6OGOjiiNUt728hidEMoX4PJWtHNWqinyRek5tSnqgaXeKC3NuU0mUIjDvBps9oH4lK3yNa5fBr/nodwP4wNyTd3obR/z6JcLersxJjHi4nYX2ju8vjdsBSIulNudqlrsPhLJe0+Tff3FRfClSQmQ/JtakHo4lIx8zxiOJY8aWFeHGdWJDkAf6NStt3eVYyOyAwISfv3muaGPZKShiIOfLyTvqFqzwYFgdTWmvFqTdwgjIMc5XAwqw73WP2BPCN+fdCiMtrw0fCrhWzw/gfMJBHdOPH0diUZysAJhM0vdVKQzEi/g3YOo00fahZiPzaxNtZnLNj2mA54YQ== +Prime1: 5YpfVjEtL1owW9gSFbIMx65POr+fiktxirgy1bc5fSsVqUgG6zhbaN/VpWcNZG0Zg5xd6S7C8V3djGlnJN8wZIyjIh7+Z3WWjqbOD9oY7rC1fR+W0OvbCmZiEzOpRJ5qoMOh1MzkkanhMy0/ICpaa8eQ9zEb80oTIQpFgoLn7K0= +Prime2: 0fs3ncL5/2qzq2dmPXLYcOfc1EGSuESO0VpREP8EpTkyPKeVw5LaF9TgZRqPWlRf2T0LPoZ766xLAn090u0pLQ5fWM96NMas7kS+rxtRssat6MiQo3YfoU3ysk3xuPzrMBHyn/N42CjSG+bJEToHR7V16KsCT6dBIPkI3tj/Yos= +Exponent1: Bdsp44ENrg+W/EDe9T69pLqFuvH4mAaktu1MHre198OJoe/8fTPK4ToUsUuXw+Akrn7mxnQy9QV4CYUG5KHtEiOkZdJ0mx8c4DbROwZNbImFl9OefWYHCJTkG6lNwDpqbf+PuWYgzraO0EdvPNrXw7grsqLGG8bgBg/FBjdgw2E= +Exponent2: uV1pxW0fwGhzX3aR/ODrTRCCEyYn3V84LHvsYHKfqTOKs5zFSrbSrIMR7G676ePeESogSPvzXSLlvLbO4urVlJ7BcOcHXJuegWBSbMZTItzdHUgg1wwp8/2Zp+nC36j1/aN6adVG8ptmj5b2HKz7TERWaCS+j454oiD1wbQSDu0= +Coefficient: JO6RxBIaoEd/Z4ITcsYT8TslP1KmIuAqdhMt3FSpqeogUDut7f3FZIEyNi4wsrSK5peIQSVmO2pQLupS+eRIPHXZ1vh5kcFAsgd7XBb7Fvsg26/WSjhB4wjx+wgWzVomK0519pfdtH854fePWPkdDKtLNL2zh0APne3GjwrbNEM= +Created: 20000101000000 +Publish: 20000101000000 +Activate: 20000101000000 diff --git a/tests/dns/time_test.c b/tests/dns/time_test.c new file mode 100644 index 0000000..f6e1948 --- /dev/null +++ b/tests/dns/time_test.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/util.h> + +#include <dns/time.h> + +#include <tests/dns.h> + +#define TEST_ORIGIN "test" + +/* value = 0xfffffffff <-> 19691231235959 */ +ISC_RUN_TEST_IMPL(epoch_minus_one) { + const char *test_text = "19691231235959"; + const uint32_t test_time = 0xffffffff; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +/* value = 0x000000000 <-> 19700101000000*/ +ISC_RUN_TEST_IMPL(epoch) { + const char *test_text = "19700101000000"; + const uint32_t test_time = 0x00000000; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +/* value = 0x7fffffff <-> 20380119031407 */ +ISC_RUN_TEST_IMPL(half_maxint) { + const char *test_text = "20380119031407"; + const uint32_t test_time = 0x7fffffff; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +/* value = 0x80000000 <-> 20380119031408 */ +ISC_RUN_TEST_IMPL(half_plus_one) { + const char *test_text = "20380119031408"; + const uint32_t test_time = 0x80000000; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +/* value = 0xef68f5d0 <-> 19610307130000 */ +ISC_RUN_TEST_IMPL(fifty_before) { + isc_result_t result; + const char *test_text = "19610307130000"; + const uint32_t test_time = 0xef68f5d0; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +/* value = 0x4d74d6d0 <-> 20110307130000 */ +ISC_RUN_TEST_IMPL(some_ago) { + const char *test_text = "20110307130000"; + const uint32_t test_time = 0x4d74d6d0; + isc_result_t result; + isc_buffer_t target; + uint32_t when; + char buf[128]; + + UNUSED(state); + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&target, buf, sizeof(buf)); + result = dns_time32_totext(test_time, &target); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, test_text); + result = dns_time32_fromtext(test_text, &when); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(when, test_time); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(epoch_minus_one) +ISC_TEST_ENTRY(epoch) +ISC_TEST_ENTRY(half_maxint) +ISC_TEST_ENTRY(half_plus_one) +ISC_TEST_ENTRY(fifty_before) +ISC_TEST_ENTRY(some_ago) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/tsig_test.c b/tests/dns/tsig_test.c new file mode 100644 index 0000000..2cc26c7 --- /dev/null +++ b/tests/dns/tsig_test.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/util.h> + +#include <dns/rdatalist.h> +#include <dns/rdataset.h> +#include <dns/tsig.h> + +#include "tsig_p.h" + +#include <tests/dns.h> + +#define TEST_ORIGIN "test" + +static int debug = 0; + +static int +setup_test(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dst_lib_init(mctx, NULL); + + if (result != ISC_R_SUCCESS) { + return (1); + } + + return (0); +} + +static int +teardown_test(void **state) { + UNUSED(state); + + dst_lib_destroy(); + + return (0); +} + +static isc_result_t +add_mac(dst_context_t *tsigctx, isc_buffer_t *buf) { + dns_rdata_any_tsig_t tsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t databuf; + isc_region_t r; + isc_result_t result; + unsigned char tsigbuf[1024]; + + isc_buffer_usedregion(buf, &r); + dns_rdata_fromregion(&rdata, dns_rdataclass_any, dns_rdatatype_tsig, + &r); + isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf)); + CHECK(dns_rdata_tostruct(&rdata, &tsig, NULL)); + isc_buffer_putuint16(&databuf, tsig.siglen); + isc_buffer_putmem(&databuf, tsig.signature, tsig.siglen); + isc_buffer_usedregion(&databuf, &r); + result = dst_context_adddata(tsigctx, &r); + dns_rdata_freestruct(&tsig); +cleanup: + return (result); +} + +static isc_result_t +add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) { + dns_compress_t cctx; + dns_rdata_any_tsig_t tsig; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_buffer_t *dynbuf = NULL; + isc_buffer_t databuf; + isc_buffer_t sigbuf; + isc_region_t r; + isc_result_t result = ISC_R_SUCCESS; + isc_stdtime_t now; + unsigned char tsigbuf[1024]; + unsigned int count; + unsigned int sigsize = 0; + bool invalidate_ctx = false; + + memset(&tsig, 0, sizeof(tsig)); + + CHECK(dns_compress_init(&cctx, -1, mctx)); + invalidate_ctx = true; + + tsig.common.rdclass = dns_rdataclass_any; + tsig.common.rdtype = dns_rdatatype_tsig; + ISC_LINK_INIT(&tsig.common, link); + dns_name_init(&tsig.algorithm, NULL); + dns_name_clone(key->algorithm, &tsig.algorithm); + + isc_stdtime_get(&now); + tsig.timesigned = now; + tsig.fudge = DNS_TSIG_FUDGE; + tsig.originalid = 50; + tsig.error = dns_rcode_noerror; + tsig.otherlen = 0; + tsig.other = NULL; + + isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf)); + isc_buffer_putuint48(&databuf, tsig.timesigned); + isc_buffer_putuint16(&databuf, tsig.fudge); + isc_buffer_usedregion(&databuf, &r); + CHECK(dst_context_adddata(tsigctx, &r)); + + CHECK(dst_key_sigsize(key->key, &sigsize)); + tsig.signature = isc_mem_get(mctx, sigsize); + isc_buffer_init(&sigbuf, tsig.signature, sigsize); + CHECK(dst_context_sign(tsigctx, &sigbuf)); + tsig.siglen = isc_buffer_usedlength(&sigbuf); + assert_int_equal(sigsize, tsig.siglen); + + isc_buffer_allocate(mctx, &dynbuf, 512); + CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any, + dns_rdatatype_tsig, &tsig, dynbuf)); + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = dns_rdataclass_any; + rdatalist.type = dns_rdatatype_tsig; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdataset_init(&rdataset); + CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); + CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx, target, 0, + &count)); + + /* + * Fixup additional record count. + */ + ((unsigned char *)target->base)[11]++; + if (((unsigned char *)target->base)[11] == 0) { + ((unsigned char *)target->base)[10]++; + } +cleanup: + if (tsig.signature != NULL) { + isc_mem_put(mctx, tsig.signature, sigsize); + } + if (dynbuf != NULL) { + isc_buffer_free(&dynbuf); + } + if (invalidate_ctx) { + dns_compress_invalidate(&cctx); + } + + return (result); +} + +static void +printmessage(dns_message_t *msg) { + isc_buffer_t b; + char *buf = NULL; + int len = 1024; + isc_result_t result = ISC_R_SUCCESS; + + if (!debug) { + return; + } + + do { + buf = isc_mem_get(mctx, len); + + isc_buffer_init(&b, buf, len); + result = dns_message_totext(msg, &dns_master_style_debug, 0, + &b); + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, buf, len); + len *= 2; + } else if (result == ISC_R_SUCCESS) { + printf("%.*s\n", (int)isc_buffer_usedlength(&b), buf); + } + } while (result == ISC_R_NOSPACE); + + if (buf != NULL) { + isc_mem_put(mctx, buf, len); + } +} + +static void +render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key, + isc_buffer_t **tsigin, isc_buffer_t **tsigout, dst_context_t *tsigctx) { + dns_message_t *msg = NULL; + dns_compress_t cctx; + isc_result_t result; + + dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &msg); + assert_non_null(msg); + + msg->id = 50; + msg->rcode = dns_rcode_noerror; + msg->flags = flags; + + /* + * XXXMPA: this hack needs to be replaced with use of + * dns_message_reply() at some point. + */ + if ((flags & DNS_MESSAGEFLAG_QR) != 0) { + msg->verified_sig = 1; + } + + if (tsigin == tsigout) { + msg->tcp_continuation = 1; + } + + if (tsigctx == NULL) { + result = dns_message_settsigkey(msg, key); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_setquerytsig(msg, *tsigin); + assert_int_equal(result, ISC_R_SUCCESS); + } + + result = dns_compress_init(&cctx, -1, mctx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_renderbegin(msg, &cctx, buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_renderend(msg); + assert_int_equal(result, ISC_R_SUCCESS); + + if (tsigctx != NULL) { + isc_region_t r; + + isc_buffer_usedregion(buf, &r); + result = dst_context_adddata(tsigctx, &r); + assert_int_equal(result, ISC_R_SUCCESS); + } else { + if (tsigin == tsigout && *tsigin != NULL) { + isc_buffer_free(tsigin); + } + + result = dns_message_getquerytsig(msg, mctx, tsigout); + assert_int_equal(result, ISC_R_SUCCESS); + } + + dns_compress_invalidate(&cctx); + dns_message_detach(&msg); +} + +/* + * Test tsig tcp-continuation validation: + * Check that a simulated three message TCP sequence where the first + * and last messages contain TSIGs but the intermediate message doesn't + * correctly verifies. + */ +ISC_RUN_TEST_IMPL(tsig_tcp) { + const dns_name_t *tsigowner = NULL; + dns_fixedname_t fkeyname; + dns_message_t *msg = NULL; + dns_name_t *keyname; + dns_tsig_keyring_t *ring = NULL; + dns_tsigkey_t *key = NULL; + isc_buffer_t *buf = NULL; + isc_buffer_t *querytsig = NULL; + isc_buffer_t *tsigin = NULL; + isc_buffer_t *tsigout = NULL; + isc_result_t result; + unsigned char secret[16] = { 0 }; + dst_context_t *tsigctx = NULL; + dst_context_t *outctx = NULL; + + UNUSED(state); + + /* isc_log_setdebuglevel(lctx, 99); */ + + keyname = dns_fixedname_initname(&fkeyname); + result = dns_name_fromstring(keyname, "test", 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_tsigkeyring_create(mctx, &ring); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_tsigkey_create(keyname, dns_tsig_hmacsha256_name, secret, + sizeof(secret), false, NULL, 0, 0, mctx, + ring, &key); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(key); + + /* + * Create request. + */ + isc_buffer_allocate(mctx, &buf, 65535); + render(buf, 0, key, &tsigout, &querytsig, NULL); + isc_buffer_free(&buf); + + /* + * Create response message 1. + */ + isc_buffer_allocate(mctx, &buf, 65535); + render(buf, DNS_MESSAGEFLAG_QR, key, &querytsig, &tsigout, NULL); + assert_non_null(tsigout); + + /* + * Process response message 1. + */ + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + assert_non_null(msg); + + result = dns_message_settsigkey(msg, key); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_parse(msg, buf, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + printmessage(msg); + + result = dns_message_setquerytsig(msg, querytsig); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(msg->verified_sig, 1); + assert_int_equal(msg->tsigstatus, dns_rcode_noerror); + + /* + * Check that we have a TSIG in the first message. + */ + assert_non_null(dns_message_gettsig(msg, &tsigowner)); + + result = dns_message_getquerytsig(msg, mctx, &tsigin); + assert_int_equal(result, ISC_R_SUCCESS); + + tsigctx = msg->tsigctx; + msg->tsigctx = NULL; + isc_buffer_free(&buf); + dns_message_detach(&msg); + + result = dst_context_create(key->key, mctx, DNS_LOGCATEGORY_DNSSEC, + false, 0, &outctx); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(outctx); + + /* + * Start digesting. + */ + result = add_mac(outctx, tsigout); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Create response message 2. + */ + isc_buffer_allocate(mctx, &buf, 65535); + + assert_int_equal(result, ISC_R_SUCCESS); + render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx); + + /* + * Process response message 2. + */ + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + assert_non_null(msg); + + msg->tcp_continuation = 1; + msg->tsigctx = tsigctx; + tsigctx = NULL; + + result = dns_message_settsigkey(msg, key); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_parse(msg, buf, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + printmessage(msg); + + result = dns_message_setquerytsig(msg, tsigin); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(msg->verified_sig, 0); + assert_int_equal(msg->tsigstatus, dns_rcode_noerror); + + /* + * Check that we don't have a TSIG in the second message. + */ + tsigowner = NULL; + assert_true(dns_message_gettsig(msg, &tsigowner) == NULL); + + tsigctx = msg->tsigctx; + msg->tsigctx = NULL; + isc_buffer_free(&buf); + dns_message_detach(&msg); + + /* + * Create response message 3. + */ + isc_buffer_allocate(mctx, &buf, 65535); + render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx); + + result = add_tsig(outctx, key, buf); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Process response message 3. + */ + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); + assert_non_null(msg); + + msg->tcp_continuation = 1; + msg->tsigctx = tsigctx; + tsigctx = NULL; + + result = dns_message_settsigkey(msg, key); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_message_parse(msg, buf, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + printmessage(msg); + + /* + * Check that we had a TSIG in the third message. + */ + assert_non_null(dns_message_gettsig(msg, &tsigowner)); + + result = dns_message_setquerytsig(msg, tsigin); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_tsig_verify(buf, msg, NULL, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(msg->verified_sig, 1); + assert_int_equal(msg->tsigstatus, dns_rcode_noerror); + + if (tsigin != NULL) { + isc_buffer_free(&tsigin); + } + + result = dns_message_getquerytsig(msg, mctx, &tsigin); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_free(&buf); + dns_message_detach(&msg); + + if (outctx != NULL) { + dst_context_destroy(&outctx); + } + if (querytsig != NULL) { + isc_buffer_free(&querytsig); + } + if (tsigin != NULL) { + isc_buffer_free(&tsigin); + } + if (tsigout != NULL) { + isc_buffer_free(&tsigout); + } + dns_tsigkey_detach(&key); + if (ring != NULL) { + dns_tsigkeyring_detach(&ring); + } +} + +/* Tests the dns__tsig_algvalid function */ +ISC_RUN_TEST_IMPL(algvalid) { + UNUSED(state); + + assert_true(dns__tsig_algvalid(DST_ALG_HMACMD5)); + + assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA1)); + assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA224)); + assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA256)); + assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA384)); + assert_true(dns__tsig_algvalid(DST_ALG_HMACSHA512)); + + assert_false(dns__tsig_algvalid(DST_ALG_GSSAPI)); +} + +/* Tests the dns__tsig_algfromname function */ +ISC_RUN_TEST_IMPL(algfromname) { + UNUSED(state); + + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACMD5_NAME), + DST_ALG_HMACMD5); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA1_NAME), + DST_ALG_HMACSHA1); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA224_NAME), + DST_ALG_HMACSHA224); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA256_NAME), + DST_ALG_HMACSHA256); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA384_NAME), + DST_ALG_HMACSHA384); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_HMACSHA512_NAME), + DST_ALG_HMACSHA512); + + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_GSSAPI_NAME), + DST_ALG_GSSAPI); + assert_int_equal(dns__tsig_algfromname(DNS_TSIG_GSSAPIMS_NAME), + DST_ALG_GSSAPI); + + assert_int_equal(dns__tsig_algfromname(dns_rootname), 0); +} + +/* Tests the dns__tsig_algnamefromname function */ + +/* + * Helper function to create a dns_name_t from a string and see if + * the dns__tsig_algnamefromname function can correctly match it against the + * static table of known algorithms. + */ +static void +test_name(const char *name_string, const dns_name_t *expected) { + dns_name_t name; + dns_name_init(&name, NULL); + assert_int_equal(dns_name_fromstring(&name, name_string, 0, mctx), + ISC_R_SUCCESS); + assert_ptr_equal(dns__tsig_algnamefromname(&name), expected); + dns_name_free(&name, mctx); +} + +ISC_RUN_TEST_IMPL(algnamefromname) { + UNUSED(state); + + /* test the standard algorithms */ + test_name("hmac-md5.sig-alg.reg.int", DNS_TSIG_HMACMD5_NAME); + test_name("hmac-sha1", DNS_TSIG_HMACSHA1_NAME); + test_name("hmac-sha224", DNS_TSIG_HMACSHA224_NAME); + test_name("hmac-sha256", DNS_TSIG_HMACSHA256_NAME); + test_name("hmac-sha384", DNS_TSIG_HMACSHA384_NAME); + test_name("hmac-sha512", DNS_TSIG_HMACSHA512_NAME); + + test_name("gss-tsig", DNS_TSIG_GSSAPI_NAME); + test_name("gss.microsoft.com", DNS_TSIG_GSSAPIMS_NAME); + + /* try another name that isn't a standard algorithm name */ + assert_null(dns__tsig_algnamefromname(dns_rootname)); +} + +/* Tests the dns__tsig_algallocated function */ +ISC_RUN_TEST_IMPL(algallocated) { + UNUSED(state); + + /* test the standard algorithms */ + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACMD5_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA1_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA224_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA256_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA384_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME)); + + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME)); + assert_false(dns__tsig_algallocated(DNS_TSIG_HMACSHA512_NAME)); + + /* try another name that isn't a standard algorithm name */ + assert_true(dns__tsig_algallocated(dns_rootname)); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(tsig_tcp, setup_test, teardown_test) +ISC_TEST_ENTRY(algvalid) +ISC_TEST_ENTRY(algfromname) +ISC_TEST_ENTRY_CUSTOM(algnamefromname, setup_test, teardown_test) +ISC_TEST_ENTRY(algallocated) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/update_test.c b/tests/dns/update_test.c new file mode 100644 index 0000000..afeaa5c --- /dev/null +++ b/tests/dns/update_test.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/serial.h> +#include <isc/stdtime.h> +#include <isc/util.h> + +#include <dns/update.h> +#define KEEP_BEFORE + +/* + * Fix the linking order problem for overridden isc_stdtime_get() by making + * everything local. This also allows static functions from update.c to be + * tested. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#undef CHECK +#include "update.c" +#pragma GCC diagnostic pop + +#undef CHECK +#include <tests/dns.h> + +static int +setup_test(void **state) { + UNUSED(state); + + setenv("TZ", "", 1); + + return (0); +} + +static uint32_t mystdtime; + +static void +set_mystdtime(int year, int month, int day) { + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + mystdtime = timegm(&tm); +} + +void +isc_stdtime_get(isc_stdtime_t *now) { + *now = mystdtime; +} + +/* simple increment by 1 */ +ISC_RUN_TEST_IMPL(increment) { + uint32_t old = 50; + uint32_t serial; + + UNUSED(state); + + serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 51); +} + +/* increment past zero, 0xfffffffff -> 1 */ +ISC_RUN_TEST_IMPL(increment_past_zero) { + uint32_t old = 0xffffffffu; + uint32_t serial; + + UNUSED(state); + + serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 1u); +} + +/* past to unixtime */ +ISC_RUN_TEST_IMPL(past_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime - 1; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, mystdtime); +} + +/* now to unixtime */ +ISC_RUN_TEST_IMPL(now_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, old + 1); +} + +/* future to unixtime */ +ISC_RUN_TEST_IMPL(future_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime + 1; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, old + 1); +} + +/* undefined plus 1 to unixtime */ +ISC_RUN_TEST_IMPL(undefined_plus1_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + old += 1; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, mystdtime); +} + +/* undefined minus 1 to unixtime */ +ISC_RUN_TEST_IMPL(undefined_minus1_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + old -= 1; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, old + 1); +} + +/* undefined to unixtime */ +ISC_RUN_TEST_IMPL(undefined_to_unix) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + set_mystdtime(2011, 6, 22); + old = mystdtime ^ 0x80000000u; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, old + 1); +} + +/* handle unixtime being zero */ +ISC_RUN_TEST_IMPL(unixtime_zero) { + uint32_t old; + uint32_t serial; + + UNUSED(state); + + mystdtime = 0; + old = 0xfffffff0; + + serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, old + 1); +} + +/* past to date */ +ISC_RUN_TEST_IMPL(past_to_date) { + uint32_t old, serial; + dns_updatemethod_t used = dns_updatemethod_none; + + UNUSED(state); + + set_mystdtime(2014, 3, 31); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); + set_mystdtime(2014, 4, 1); + + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040100); + assert_int_equal(dns_updatemethod_date, used); +} + +/* now to date */ +ISC_RUN_TEST_IMPL(now_to_date) { + uint32_t old; + uint32_t serial; + dns_updatemethod_t used = dns_updatemethod_none; + + UNUSED(state); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); + + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040101); + assert_int_equal(dns_updatemethod_date, used); + + old = 2014040198; + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040199); + assert_int_equal(dns_updatemethod_date, used); + + /* + * Stealing from "tomorrow". + */ + old = 2014040199; + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040200); + assert_int_equal(dns_updatemethod_increment, used); +} + +/* future to date */ +ISC_RUN_TEST_IMPL(future_to_date) { + uint32_t old; + uint32_t serial; + dns_updatemethod_t used = dns_updatemethod_none; + + UNUSED(state); + + set_mystdtime(2014, 4, 1); + old = dns_update_soaserial(0, dns_updatemethod_date, NULL); + set_mystdtime(2014, 3, 31); + + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040101); + assert_int_equal(dns_updatemethod_increment, used); + + old = serial; + serial = dns_update_soaserial(old, dns_updatemethod_date, &used); + assert_true(isc_serial_lt(old, serial)); + assert_int_not_equal(serial, 0); + assert_int_equal(serial, 2014040102); + assert_int_equal(dns_updatemethod_increment, used); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(increment, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(increment_past_zero, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(past_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(now_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(future_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(undefined_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(undefined_plus1_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(undefined_minus1_to_unix, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(unixtime_zero, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(past_to_date, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(now_to_date, setup_test, NULL) +ISC_TEST_ENTRY_CUSTOM(future_to_date, setup_test, NULL) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/zonemgr_test.c b/tests/dns/zonemgr_test.c new file mode 100644 index 0000000..0cbbca4 --- /dev/null +++ b/tests/dns/zonemgr_test.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include <tests/dns.h> + +/* create zone manager */ +ISC_RUN_TEST_IMPL(dns_zonemgr_create) { + dns_zonemgr_t *myzonemgr = NULL; + isc_result_t result; + + UNUSED(state); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, netmgr, + &myzonemgr); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + assert_null(myzonemgr); +} + +/* manage and release a zone */ +ISC_RUN_TEST_IMPL(dns_zonemgr_managezone) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_result_t result; + + UNUSED(state); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, netmgr, + &myzonemgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + /* This should not succeed until the dns_zonemgr_setsize() is run */ + result = dns_zonemgr_managezone(myzonemgr, zone); + assert_int_equal(result, ISC_R_FAILURE); + + assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0); + + result = dns_zonemgr_setsize(myzonemgr, 1); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Now it should succeed */ + result = dns_zonemgr_managezone(myzonemgr, zone); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 1); + + dns_zonemgr_releasezone(myzonemgr, zone); + dns_zone_detach(&zone); + + assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + assert_null(myzonemgr); +} + +/* create and release a zone */ +ISC_RUN_TEST_IMPL(dns_zonemgr_createzone) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_result_t result; + + UNUSED(state); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, netmgr, + &myzonemgr); + assert_int_equal(result, ISC_R_SUCCESS); + + /* This should not succeed until the dns_zonemgr_setsize() is run */ + result = dns_zonemgr_createzone(myzonemgr, &zone); + assert_int_equal(result, ISC_R_FAILURE); + + result = dns_zonemgr_setsize(myzonemgr, 1); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Now it should succeed */ + result = dns_zonemgr_createzone(myzonemgr, &zone); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(zone); + + result = dns_zonemgr_managezone(myzonemgr, zone); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_zone_detach(&zone); + + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + assert_null(myzonemgr); +} + +/* manage and release a zone */ +ISC_RUN_TEST_IMPL(dns_zonemgr_unreachable) { + dns_zonemgr_t *myzonemgr = NULL; + dns_zone_t *zone = NULL; + isc_sockaddr_t addr1, addr2; + struct in_addr in; + isc_result_t result; + isc_time_t now; + + UNUSED(state); + + TIME_NOW(&now); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, netmgr, + &myzonemgr); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_makezone("foo", &zone, NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zonemgr_setsize(myzonemgr, 1); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zonemgr_managezone(myzonemgr, zone); + assert_int_equal(result, ISC_R_SUCCESS); + + in.s_addr = inet_addr("10.53.0.1"); + isc_sockaddr_fromin(&addr1, &in, 2112); + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&addr2, &in, 5150); + assert_false(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + /* + * We require multiple unreachableadd calls to mark a server as + * unreachable. + */ + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + assert_false(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + assert_true(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + in.s_addr = inet_addr("10.53.0.3"); + isc_sockaddr_fromin(&addr2, &in, 5150); + assert_false(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + /* + * We require multiple unreachableadd calls to mark a server as + * unreachable. + */ + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + dns_zonemgr_unreachableadd(myzonemgr, &addr1, &addr2, &now); + assert_true(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + dns_zonemgr_unreachabledel(myzonemgr, &addr1, &addr2); + assert_false(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + in.s_addr = inet_addr("10.53.0.2"); + isc_sockaddr_fromin(&addr2, &in, 5150); + assert_true(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + dns_zonemgr_unreachabledel(myzonemgr, &addr1, &addr2); + assert_false(dns_zonemgr_unreachable(myzonemgr, &addr1, &addr2, &now)); + + dns_zonemgr_releasezone(myzonemgr, zone); + dns_zone_detach(&zone); + dns_zonemgr_shutdown(myzonemgr); + dns_zonemgr_detach(&myzonemgr); + assert_null(myzonemgr); +} + +/* + * XXX: + * dns_zonemgr API calls that are not yet part of this unit test: + * + * - dns_zonemgr_attach + * - dns_zonemgr_forcemaint + * - dns_zonemgr_resumexfrs + * - dns_zonemgr_shutdown + * - dns_zonemgr_setsize + * - dns_zonemgr_settransfersin + * - dns_zonemgr_getttransfersin + * - dns_zonemgr_settransfersperns + * - dns_zonemgr_getttransfersperns + * - dns_zonemgr_setiolimit + * - dns_zonemgr_getiolimit + * - dns_zonemgr_dbdestroyed + * - dns_zonemgr_setserialqueryrate + * - dns_zonemgr_getserialqueryrate + */ + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_zonemgr_create, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_zonemgr_managezone, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_zonemgr_createzone, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(dns_zonemgr_unreachable, setup_managers, + teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/dns/zt_test.c b/tests/dns/zt_test.c new file mode 100644 index 0000000..c38e601 --- /dev/null +++ b/tests/dns/zt_test.c @@ -0,0 +1,352 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/app.h> +#include <isc/atomic.h> +#include <isc/buffer.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> +#include <dns/zt.h> + +#include <tests/dns.h> + +static int +_setup(void **state) { + isc_app_start(); + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + isc_app_finish(); + + return (0); +} + +struct args { + void *arg1; + void *arg2; + bool arg3; +}; + +static isc_result_t +count_zone(dns_zone_t *zone, void *uap) { + int *nzones = (int *)uap; + + UNUSED(zone); + + *nzones += 1; + return (ISC_R_SUCCESS); +} + +static isc_result_t +load_done(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) { + /* We treat zt as a pointer to a boolean for testing purposes */ + atomic_bool *done = (atomic_bool *)zt; + + UNUSED(zone); + UNUSED(task); + + atomic_store(done, true); + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static isc_result_t +all_done(void *arg) { + atomic_bool *done = (atomic_bool *)arg; + + atomic_store(done, true); + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static void +start_zt_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zt_asyncload(args->arg1, false, all_done, args->arg2); + + isc_event_free(&event); +} + +static void +start_zone_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zone_asyncload(args->arg1, args->arg3, load_done, args->arg2); + isc_event_free(&event); +} + +/* apply a function to a zone table */ +ISC_RUN_TEST_IMPL(dns_zt_apply) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + int nzones = 0; + + UNUSED(state); + + result = dns_test_makezone("foo", &zone, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + assert_non_null(view->zonetable); + + assert_int_equal(nzones, 0); + result = dns_zt_apply(view->zonetable, isc_rwlocktype_read, false, NULL, + count_zone, &nzones); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(nzones, 1); + + /* These steps are necessary so the zone can be detached properly */ + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + assert_int_equal(result, ISC_R_SUCCESS); + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + /* The view was left attached in dns_test_makezone() */ + dns_view_detach(&view); + dns_zone_detach(&zone); +} + +/* asynchronous zone load */ +ISC_RUN_TEST_IMPL(dns_zt_asyncload_zone) { + isc_result_t result; + int n; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + dns_db_t *db = NULL; + FILE *zonefile, *origfile; + char buf[4096]; + atomic_bool done; + int i = 0; + struct args args; + + UNUSED(state); + + atomic_init(&done, false); + + result = dns_test_makezone("foo", &zone, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + assert_int_equal(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + assert_non_null(view->zonetable); + + assert_false(dns__zone_loadpending(zone)); + assert_false(atomic_load(&done)); + zonefile = fopen("./zone.data", "wb"); + assert_non_null(zonefile); + origfile = fopen(TESTS_DIR "/testdata/zt/zone1.db", "r+b"); + assert_non_null(origfile); + n = fread(buf, 1, 4096, origfile); + fclose(origfile); + fwrite(buf, 1, n, zonefile); + fflush(zonefile); + + dns_zone_setfile(zone, "./zone.data", dns_masterformat_text, + &dns_master_style_default); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detach(&db); + /* + * Add something to zone file, reload zone with newonly - it should + * not be reloaded. + */ + fprintf(zonefile, "\nb in b 1.2.3.4\n"); + fflush(zonefile); + fclose(zonefile); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = true; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detach(&db); + + /* Now reload it without newonly - it should be reloaded */ + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + dns_zone_detach(&zone); + dns_view_detach(&view); +} + +/* asynchronous zone table load */ +ISC_RUN_TEST_IMPL(dns_zt_asyncload_zt) { + isc_result_t result; + dns_zone_t *zone1 = NULL, *zone2 = NULL, *zone3 = NULL; + dns_view_t *view; + dns_zt_t *zt = NULL; + dns_db_t *db = NULL; + atomic_bool done; + int i = 0; + struct args args; + + UNUSED(state); + + atomic_init(&done, false); + + result = dns_test_makezone("foo", &zone1, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone1, TESTS_DIR "/testdata/zt/zone1.db", + dns_masterformat_text, &dns_master_style_default); + view = dns_zone_getview(zone1); + + result = dns_test_makezone("bar", &zone2, view, false); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone2, TESTS_DIR "/testdata/zt/zone1.db", + dns_masterformat_text, &dns_master_style_default); + + /* This one will fail to load */ + result = dns_test_makezone("fake", &zone3, view, false); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone3, TESTS_DIR "/testdata/zt/nonexistent.db", + dns_masterformat_text, &dns_master_style_default); + + zt = view->zonetable; + assert_non_null(zt); + + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone1); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone2); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone3); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(dns__zone_loadpending(zone1)); + assert_false(dns__zone_loadpending(zone2)); + assert_false(atomic_load(&done)); + + args.arg1 = zt; + args.arg2 = &done; + isc_app_onrun(mctx, maintask, start_zt_asyncload, &args); + + isc_app_run(); + while (!atomic_load(&done) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + + /* Both zones should now be loaded; test them */ + result = dns_zone_getdb(zone1, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + result = dns_zone_getdb(zone2, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + dns_test_releasezone(zone3); + dns_test_releasezone(zone2); + dns_test_releasezone(zone1); + dns_test_closezonemgr(); + + dns_zone_detach(&zone1); + dns_zone_detach(&zone2); + dns_zone_detach(&zone3); + dns_view_detach(&view); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_zt_apply, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_zt_asyncload_zone, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_zt_asyncload_zt, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/include/tests/dns.h b/tests/include/tests/dns.h new file mode 100644 index 0000000..64a265b --- /dev/null +++ b/tests/include/tests/dns.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/buffer.h> +#include <isc/hash.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/cache.h> +#include <dns/diff.h> +#include <dns/zone.h> + +#include <tests/isc.h> + +extern dns_zonemgr_t *zonemgr; + +typedef struct { + dns_diffop_t op; + const char *owner; + dns_ttl_t ttl; + const char *type; + const char *rdata; +} zonechange_t; + +#define ZONECHANGE_SENTINEL \ + { \ + 0, NULL, 0, NULL, NULL \ + } + +isc_result_t +dns_test_makeview(const char *name, bool with_cache, dns_view_t **viewp); + +/*% + * Create a zone with origin 'name', return a pointer to the zone object in + * 'zonep'. + * + * If 'view' is set, the returned zone will be assigned to the passed view. + * 'createview' must be set to false when 'view' is non-NULL. + * + * If 'view' is not set and 'createview' is true, a new view is also created + * and the returned zone is assigned to it. This imposes two requirements on + * the caller: 1) the returned zone has to be subsequently assigned to a zone + * manager, otherwise its cleanup will fail, 2) the created view has to be + * cleaned up by the caller. + * + * If 'view' is not set and 'createview' is false, the returned zone will not + * be assigned to any view. + */ +isc_result_t +dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, + bool createview); + +isc_result_t +dns_test_setupzonemgr(void); + +isc_result_t +dns_test_managezone(dns_zone_t *zone); + +void +dns_test_releasezone(dns_zone_t *zone); + +void +dns_test_closezonemgr(void); + +void +dns_test_nap(uint32_t usec); + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile); + +isc_result_t +dns_test_getdata(const char *file, unsigned char *buf, size_t bufsiz, + size_t *sizep); + +char * +dns_test_tohex(const unsigned char *data, size_t len, char *buf, size_t buflen); + +/*% + * Try parsing text form RDATA in "src" (of class "rdclass" and type "rdtype") + * into a structure representing that RDATA at "rdata", storing the + * uncompressed wire form of that RDATA at "dst", which is "dstlen" bytes long. + * Set 'warnings' to true to print logged warnings from dns_rdata_fromtext(). + */ +isc_result_t +dns_test_rdatafromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src, bool warnings); + +void +dns_test_namefromstring(const char *namestr, dns_fixedname_t *fname); + +/*% + * Given a pointer to an uninitialized dns_diff_t structure in 'diff', make it + * contain diff tuples representing zone database changes listed in 'changes'. + * Set 'warnings' to true to print logged warnings from dns_rdata_fromtext(). + */ +isc_result_t +dns_test_difffromchanges(dns_diff_t *diff, const zonechange_t *changes, + bool warnings); diff --git a/tests/include/tests/isc.h b/tests/include/tests/isc.h new file mode 100644 index 0000000..6131c20 --- /dev/null +++ b/tests/include/tests/isc.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include <inttypes.h> +#include <stdbool.h> +#include <uv.h> + +#include <isc/buffer.h> +#include <isc/hash.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/netmgr.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include "netmgr_p.h" +#include "task_p.h" +#include "timer_p.h" + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +extern isc_mem_t *mctx; +extern isc_nm_t *netmgr; +extern isc_taskmgr_t *taskmgr; +extern isc_timermgr_t *timermgr; +extern unsigned int workers; +extern isc_task_t *maintask; + +#define isc_test_nap(ms) uv_sleep(ms) + +int +setup_managers(void **state); +int +teardown_managers(void **state); + +#ifndef TESTS_DIR +#define TESTS_DIR "./" +#endif + +/* clang-format off */ +/* Copied from cmocka */ +#define ISC_TEST_ENTRY(name) \ + { #name, run_test_##name, NULL, NULL, NULL }, +#define ISC_TEST_ENTRY_SETUP(name) \ + { #name, run_test_##name, setup_test_##name, NULL, NULL }, +#define ISC_TEST_ENTRY_TEARDOWN(name) \ + { #name, run_test_##name, NULL, teardown_test_##name, NULL }, +#define ISC_TEST_ENTRY_SETUP_TEARDOWN(name) \ + { #name, run_test_##name, setup_test_##name, teardown_test_##name, NULL }, +#define ISC_TEST_ENTRY_CUSTOM(name, setup, teardown) \ + { #name, run_test_##name, setup, teardown, NULL }, +/* clang-format on */ + +#define ISC_SETUP_TEST_DECLARE(name) \ + int setup_test_##name(void **state __attribute__((unused))); + +#define ISC_RUN_TEST_DECLARE(name) \ + void run_test_##name(void **state __attribute__((unused))); + +#define ISC_TEARDOWN_TEST_DECLARE(name) \ + int teardown_test_##name(void **state __attribute__((unused))) + +#define ISC_SETUP_TEST_IMPL(name) \ + int setup_test_##name(void **state __attribute__((unused))); \ + int setup_test_##name(void **state __attribute__((unused))) + +#define ISC_RUN_TEST_IMPL(name) \ + void run_test_##name(void **state __attribute__((unused))); \ + void run_test_##name(void **state __attribute__((unused))) + +#define ISC_TEARDOWN_TEST_IMPL(name) \ + int teardown_test_##name(void **state __attribute__((unused))); \ + int teardown_test_##name(void **state __attribute__((unused))) + +#define ISC_TEST_LIST_START const struct CMUnitTest tests[] = { +#define ISC_TEST_LIST_END \ + } \ + ; + +#define ISC_TEST_MAIN ISC_TEST_MAIN_CUSTOM(NULL, NULL) + +#define ISC_TEST_MAIN_CUSTOM(setup, teardown) \ + int main(void) { \ + int r; \ + \ + signal(SIGPIPE, SIG_IGN); \ + \ + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; \ + isc_mem_create(&mctx); \ + \ + r = cmocka_run_group_tests(tests, setup, teardown); \ + \ + isc_mem_destroy(&mctx); \ + \ + return (r); \ + } diff --git a/tests/include/tests/ns.h b/tests/include/tests/ns.h new file mode 100644 index 0000000..175cb90 --- /dev/null +++ b/tests/include/tests/ns.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/buffer.h> +#include <isc/hash.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/zone.h> + +#include <ns/client.h> +#include <ns/hooks.h> +#include <ns/interfacemgr.h> + +#include <tests/dns.h> + +typedef struct ns_test_id { + const char *description; + int lineno; +} ns_test_id_t; + +#define NS_TEST_ID(desc) \ + { \ + .description = desc, .lineno = __LINE__ \ + } + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +extern dns_dispatchmgr_t *dispatchmgr; +extern ns_clientmgr_t *clientmgr; +extern ns_interfacemgr_t *interfacemgr; +extern ns_server_t *sctx; + +#ifdef NETMGR_TRACE +#define FLARG \ + , const char *file __attribute__((unused)), \ + unsigned int line __attribute__((unused)), \ + const char *func __attribute__((unused)) +#else +#define FLARG +#endif + +int +setup_server(void **state); +int +teardown_server(void **state); + +/*% + * Load data for zone "zonename" from file "filename" and start serving it to + * clients matching "view". Only one zone loaded using this function can be + * served at any given time. + */ +isc_result_t +ns_test_serve_zone(const char *zonename, const char *filename, + dns_view_t *view); + +/*% + * Release the zone loaded by ns_test_serve_zone(). + */ +void +ns_test_cleanup_zone(void); + +isc_result_t +ns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile); + +isc_result_t +ns_test_getdata(const char *file, unsigned char *buf, size_t bufsiz, + size_t *sizep); + +isc_result_t +ns_test_getclient(ns_interface_t *ifp0, bool tcp, ns_client_t **clientp); + +/*% + * Structure containing parameters for ns_test_qctx_create(). + */ +typedef struct ns_test_qctx_create_params { + const char *qname; + dns_rdatatype_t qtype; + unsigned int qflags; + bool with_cache; +} ns_test_qctx_create_params_t; + +/*% + * Prepare a query context identical with one that would be prepared if a query + * with given QNAME, QTYPE and flags was received from a client. Recursion is + * assumed to be allowed for this client. If "with_cache" is set to true, + * a cache database will be created and associated with the view matching the + * incoming query. + */ +isc_result_t +ns_test_qctx_create(const ns_test_qctx_create_params_t *params, + query_ctx_t **qctxp); + +/*% + * Destroy a query context created by ns_test_qctx_create(). + */ +void +ns_test_qctx_destroy(query_ctx_t **qctxp); + +/*% + * A hook callback interrupting execution at given hook's insertion point. + */ +ns_hookresult_t +ns_test_hook_catch_call(void *arg, void *data, isc_result_t *resultp); diff --git a/tests/irs/Makefile.am b/tests/irs/Makefile.am new file mode 100644 index 0000000..8e6e52f --- /dev/null +++ b/tests/irs/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBIRS_CFLAGS) + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBIRS_LIBS) + +check_PROGRAMS = \ + resconf_test + +EXTRA_DIST = testdata + +include $(top_srcdir)/Makefile.tests diff --git a/tests/irs/Makefile.in b/tests/irs/Makefile.in new file mode 100644 index 0000000..e5500c1 --- /dev/null +++ b/tests/irs/Makefile.in @@ -0,0 +1,1152 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = resconf_test$(EXEEXT) +subdir = tests/irs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +resconf_test_SOURCES = resconf_test.c +resconf_test_OBJECTS = resconf_test.$(OBJEXT) +resconf_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +resconf_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBIRS_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/resconf_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = resconf_test.c +DIST_SOURCES = resconf_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBIRS_CFLAGS) \ + $(CMOCKA_CFLAGS) -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBIRS_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +EXTRA_DIST = testdata +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/irs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/irs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +resconf_test$(EXEEXT): $(resconf_test_OBJECTS) $(resconf_test_DEPENDENCIES) $(EXTRA_resconf_test_DEPENDENCIES) + @rm -f resconf_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(resconf_test_OBJECTS) $(resconf_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resconf_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +resconf_test.log: resconf_test$(EXEEXT) + @p='resconf_test$(EXEEXT)'; \ + b='resconf_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/resconf_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/resconf_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/irs/resconf_test.c b/tests/irs/resconf_test.c new file mode 100644 index 0000000..367898f --- /dev/null +++ b/tests/irs/resconf_test.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#if HAVE_CMOCKA + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/mem.h> +#include <isc/util.h> + +#include <irs/resconf.h> + +static isc_mem_t *mctx = NULL; + +static void +setup_test(void) { + isc_mem_create(&mctx); + + /* + * the caller might run from another directory, but tests + * that access test data files must first chdir to the proper + * location. + */ + assert_return_code(chdir(TESTS_DIR), 0); +} + +static isc_result_t +check_number(unsigned int n, unsigned int expected) { + return ((n == expected) ? ISC_R_SUCCESS : ISC_R_BADNUMBER); +} + +static isc_result_t +check_attempts(irs_resconf_t *resconf) { + return (check_number(irs_resconf_getattempts(resconf), 4)); +} + +static isc_result_t +check_timeout(irs_resconf_t *resconf) { + return (check_number(irs_resconf_gettimeout(resconf), 1)); +} + +static isc_result_t +check_ndots(irs_resconf_t *resconf) { + return (check_number(irs_resconf_getndots(resconf), 2)); +} + +static isc_result_t +check_options(irs_resconf_t *resconf) { + if (irs_resconf_getattempts(resconf) != 3) { + return ISC_R_BADNUMBER; /* default value only */ + } + + if (irs_resconf_getndots(resconf) != 2) { + return ISC_R_BADNUMBER; + } + + if (irs_resconf_gettimeout(resconf) != 1) { + return ISC_R_BADNUMBER; + } + + return (ISC_R_SUCCESS); +} + +/* test irs_resconf_load() */ +static void +irs_resconf_load_test(void **state) { + isc_result_t result; + irs_resconf_t *resconf = NULL; + unsigned int i; + struct { + const char *file; + isc_result_t loadres; + isc_result_t (*check)(irs_resconf_t *resconf); + isc_result_t checkres; + } tests[] = { + { "testdata/domain.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, + { "testdata/nameserver-v4.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/nameserver-v6.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/nameserver-v6-scoped.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/options-attempts.conf", ISC_R_SUCCESS, + check_attempts, ISC_R_SUCCESS }, + { "testdata/options-debug.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/options-ndots.conf", ISC_R_SUCCESS, check_ndots, + ISC_R_SUCCESS }, + { "testdata/options-timeout.conf", ISC_R_SUCCESS, check_timeout, + ISC_R_SUCCESS }, + { "testdata/options-unknown.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/options.conf", ISC_R_SUCCESS, check_options, + ISC_R_SUCCESS }, + { "testdata/options-bad-ndots.conf", ISC_R_RANGE, NULL, + ISC_R_SUCCESS }, + { "testdata/options-empty.conf", ISC_R_UNEXPECTEDEND, NULL, + ISC_R_SUCCESS }, + { "testdata/port.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, + { "testdata/resolv.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, + { "testdata/search.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, + { "testdata/sortlist-v4.conf", ISC_R_SUCCESS, NULL, + ISC_R_SUCCESS }, + { "testdata/timeout.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, + { "testdata/unknown.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS } + }; + + UNUSED(state); + + setup_test(); + + for (i = 0; i < sizeof(tests) / sizeof(tests[1]); i++) { + result = irs_resconf_load(mctx, tests[i].file, &resconf); + if (result != tests[i].loadres) { + fail_msg("# unexpected result %s loading %s", + isc_result_totext(result), tests[i].file); + } + + if (result == ISC_R_SUCCESS && resconf == NULL) { + fail_msg("# NULL on success loading %s", tests[i].file); + } else if (result != ISC_R_SUCCESS && resconf != NULL) { + fail_msg("# non-NULL on failure loading %s", + tests[i].file); + } + + if (resconf != NULL && tests[i].check != NULL) { + result = (tests[i].check)(resconf); + if (result != tests[i].checkres) { + fail_msg("# unexpected result %s loading %s", + isc_result_totext(result), + tests[i].file); + } + } + if (resconf != NULL) { + irs_resconf_destroy(&resconf); + } + } + + isc_mem_detach(&mctx); +} + +int +main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(irs_resconf_load_test), + }; + + return (cmocka_run_group_tests(tests, NULL, NULL)); +} + +#else /* HAVE_CMOCKA */ + +#include <stdio.h> + +int +main(void) { + printf("1..0 # Skipped: cmocka not available\n"); + return (SKIPPED_TEST_EXIT_CODE); +} + +#endif /* if HAVE_CMOCKA */ diff --git a/tests/irs/testdata/domain.conf b/tests/irs/testdata/domain.conf new file mode 100644 index 0000000..ee43f5c --- /dev/null +++ b/tests/irs/testdata/domain.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +domain example.com diff --git a/tests/irs/testdata/nameserver-v4.conf b/tests/irs/testdata/nameserver-v4.conf new file mode 100644 index 0000000..5054de0 --- /dev/null +++ b/tests/irs/testdata/nameserver-v4.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +nameserver 10.0.0.1 diff --git a/tests/irs/testdata/nameserver-v6-scoped.conf b/tests/irs/testdata/nameserver-v6-scoped.conf new file mode 100644 index 0000000..d5bd97f --- /dev/null +++ b/tests/irs/testdata/nameserver-v6-scoped.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +nameserver fe80::1%1 diff --git a/tests/irs/testdata/nameserver-v6.conf b/tests/irs/testdata/nameserver-v6.conf new file mode 100644 index 0000000..b9ed093 --- /dev/null +++ b/tests/irs/testdata/nameserver-v6.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +nameserver 2001:DB8::1 diff --git a/tests/irs/testdata/options-attempts.conf b/tests/irs/testdata/options-attempts.conf new file mode 100644 index 0000000..a076f8e --- /dev/null +++ b/tests/irs/testdata/options-attempts.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options attempts:4 diff --git a/tests/irs/testdata/options-bad-ndots.conf b/tests/irs/testdata/options-bad-ndots.conf new file mode 100644 index 0000000..18d3f8b --- /dev/null +++ b/tests/irs/testdata/options-bad-ndots.conf @@ -0,0 +1,13 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +search example.com example.net +options ndots:256 diff --git a/tests/irs/testdata/options-debug.conf b/tests/irs/testdata/options-debug.conf new file mode 100644 index 0000000..04bcf2e --- /dev/null +++ b/tests/irs/testdata/options-debug.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options debug diff --git a/tests/irs/testdata/options-empty.conf b/tests/irs/testdata/options-empty.conf new file mode 100644 index 0000000..0b1dc9e --- /dev/null +++ b/tests/irs/testdata/options-empty.conf @@ -0,0 +1,13 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +domain example.com +options diff --git a/tests/irs/testdata/options-ndots.conf b/tests/irs/testdata/options-ndots.conf new file mode 100644 index 0000000..f37c712 --- /dev/null +++ b/tests/irs/testdata/options-ndots.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options ndots:2 diff --git a/tests/irs/testdata/options-timeout.conf b/tests/irs/testdata/options-timeout.conf new file mode 100644 index 0000000..96787c4 --- /dev/null +++ b/tests/irs/testdata/options-timeout.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options timeout:1 diff --git a/tests/irs/testdata/options-unknown.conf b/tests/irs/testdata/options-unknown.conf new file mode 100644 index 0000000..fdf82b4 --- /dev/null +++ b/tests/irs/testdata/options-unknown.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options unknown diff --git a/tests/irs/testdata/options.conf b/tests/irs/testdata/options.conf new file mode 100644 index 0000000..7a8d5f3 --- /dev/null +++ b/tests/irs/testdata/options.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options unknown debug timeout:1 ndots:2 diff --git a/tests/irs/testdata/port.conf b/tests/irs/testdata/port.conf new file mode 100644 index 0000000..54e2094 --- /dev/null +++ b/tests/irs/testdata/port.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +port 5300 diff --git a/tests/irs/testdata/resolv.conf b/tests/irs/testdata/resolv.conf new file mode 100644 index 0000000..3c14408 --- /dev/null +++ b/tests/irs/testdata/resolv.conf @@ -0,0 +1,19 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +port 5300 +nameserver 10.0.0.1 +nameserver 2001:DB8::1 +search example.com example.net +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 +timeout 10 +unknown directive +options unknown debug timeout:1 ndots:2 diff --git a/tests/irs/testdata/search.conf b/tests/irs/testdata/search.conf new file mode 100644 index 0000000..f019ab9 --- /dev/null +++ b/tests/irs/testdata/search.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +search example.com example.net diff --git a/tests/irs/testdata/sortlist-v4.conf b/tests/irs/testdata/sortlist-v4.conf new file mode 100644 index 0000000..3f4d54a --- /dev/null +++ b/tests/irs/testdata/sortlist-v4.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 diff --git a/tests/irs/testdata/timeout.conf b/tests/irs/testdata/timeout.conf new file mode 100644 index 0000000..2ccb92d --- /dev/null +++ b/tests/irs/testdata/timeout.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +timeout 10 diff --git a/tests/irs/testdata/unknown.conf b/tests/irs/testdata/unknown.conf new file mode 100644 index 0000000..0eafb76 --- /dev/null +++ b/tests/irs/testdata/unknown.conf @@ -0,0 +1,12 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +unknown directive diff --git a/tests/isc/Makefile.am b/tests/isc/Makefile.am new file mode 100644 index 0000000..488ba50 --- /dev/null +++ b/tests/isc/Makefile.am @@ -0,0 +1,115 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBUV_LIBS) + +check_PROGRAMS = \ + aes_test \ + buffer_test \ + counter_test \ + crc64_test \ + errno_test \ + file_test \ + hash_test \ + heap_test \ + hmac_test \ + ht_test \ + lex_test \ + md_test \ + mem_test \ + netaddr_test \ + netmgr_test \ + parse_test \ + pool_test \ + quota_test \ + radix_test \ + random_test \ + regex_test \ + result_test \ + safe_test \ + siphash_test \ + sockaddr_test \ + stats_test \ + symtab_test \ + task_test \ + taskpool_test \ + time_test \ + timer_test + +if HAVE_LIBNGHTTP2 +check_PROGRAMS += \ + doh_test + +doh_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBNGHTTP2_CFLAGS) \ + $(OPENSSL_CFLAGS) + +doh_test_LDADD = \ + $(LDADD) \ + $(LIBNGHTTP2_LIBS) + +doh_test_SOURCES = \ + doh_test.c \ + uv_wrap.h + +endif HAVE_LIBNGHTTP2 + +hmac_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +hmac_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +md_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +md_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +netmgr_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_SOURCES = \ + netmgr_test.c \ + uv_wrap.h + +random_test_LDADD = \ + $(LDADD) \ + -lm + +task_test_CPPFLAGS = \ + $(AM_CPPFLAGS) + +task_test_LDADD = \ + $(LDADD) + +if HAVE_LIBXML2 +task_test_CPPFLAGS += $(LIBXML2_CFLAGS) +task_test_LDADD += $(LIBXML2_LIBS) +endif HAVE_LIBXML2 + +if HAVE_JSON_C +task_test_CPPFLAGS += $(JSON_C_CFLAGS) +task_test_LDADD += $(JSON_C_LIBS) +endif HAVE_JSON_C + + +EXTRA_DIST = testdata + +include $(top_srcdir)/Makefile.tests diff --git a/tests/isc/Makefile.in b/tests/isc/Makefile.in new file mode 100644 index 0000000..1060d23 --- /dev/null +++ b/tests/isc/Makefile.in @@ -0,0 +1,1905 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = aes_test$(EXEEXT) buffer_test$(EXEEXT) \ + counter_test$(EXEEXT) crc64_test$(EXEEXT) errno_test$(EXEEXT) \ + file_test$(EXEEXT) hash_test$(EXEEXT) heap_test$(EXEEXT) \ + hmac_test$(EXEEXT) ht_test$(EXEEXT) lex_test$(EXEEXT) \ + md_test$(EXEEXT) mem_test$(EXEEXT) netaddr_test$(EXEEXT) \ + netmgr_test$(EXEEXT) parse_test$(EXEEXT) pool_test$(EXEEXT) \ + quota_test$(EXEEXT) radix_test$(EXEEXT) random_test$(EXEEXT) \ + regex_test$(EXEEXT) result_test$(EXEEXT) safe_test$(EXEEXT) \ + siphash_test$(EXEEXT) sockaddr_test$(EXEEXT) \ + stats_test$(EXEEXT) symtab_test$(EXEEXT) task_test$(EXEEXT) \ + taskpool_test$(EXEEXT) time_test$(EXEEXT) timer_test$(EXEEXT) \ + $(am__EXEEXT_1) +@HAVE_LIBNGHTTP2_TRUE@am__append_2 = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test + +@HAVE_LIBXML2_TRUE@am__append_3 = $(LIBXML2_CFLAGS) +@HAVE_LIBXML2_TRUE@am__append_4 = $(LIBXML2_LIBS) +@HAVE_JSON_C_TRUE@am__append_5 = $(JSON_C_CFLAGS) +@HAVE_JSON_C_TRUE@am__append_6 = $(JSON_C_LIBS) +subdir = tests/isc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@HAVE_LIBNGHTTP2_TRUE@am__EXEEXT_1 = doh_test$(EXEEXT) +aes_test_SOURCES = aes_test.c +aes_test_OBJECTS = aes_test.$(OBJEXT) +aes_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +aes_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +buffer_test_SOURCES = buffer_test.c +buffer_test_OBJECTS = buffer_test.$(OBJEXT) +buffer_test_LDADD = $(LDADD) +buffer_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +counter_test_SOURCES = counter_test.c +counter_test_OBJECTS = counter_test.$(OBJEXT) +counter_test_LDADD = $(LDADD) +counter_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +crc64_test_SOURCES = crc64_test.c +crc64_test_OBJECTS = crc64_test.$(OBJEXT) +crc64_test_LDADD = $(LDADD) +crc64_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +am__doh_test_SOURCES_DIST = doh_test.c uv_wrap.h +@HAVE_LIBNGHTTP2_TRUE@am_doh_test_OBJECTS = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test-doh_test.$(OBJEXT) +doh_test_OBJECTS = $(am_doh_test_OBJECTS) +am__DEPENDENCIES_2 = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +@HAVE_LIBNGHTTP2_TRUE@doh_test_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@HAVE_LIBNGHTTP2_TRUE@ $(am__DEPENDENCIES_1) +errno_test_SOURCES = errno_test.c +errno_test_OBJECTS = errno_test.$(OBJEXT) +errno_test_LDADD = $(LDADD) +errno_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +file_test_SOURCES = file_test.c +file_test_OBJECTS = file_test.$(OBJEXT) +file_test_LDADD = $(LDADD) +file_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +hash_test_SOURCES = hash_test.c +hash_test_OBJECTS = hash_test.$(OBJEXT) +hash_test_LDADD = $(LDADD) +hash_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +heap_test_SOURCES = heap_test.c +heap_test_OBJECTS = heap_test.$(OBJEXT) +heap_test_LDADD = $(LDADD) +heap_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +hmac_test_SOURCES = hmac_test.c +hmac_test_OBJECTS = hmac_test-hmac_test.$(OBJEXT) +hmac_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +ht_test_SOURCES = ht_test.c +ht_test_OBJECTS = ht_test.$(OBJEXT) +ht_test_LDADD = $(LDADD) +ht_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +lex_test_SOURCES = lex_test.c +lex_test_OBJECTS = lex_test.$(OBJEXT) +lex_test_LDADD = $(LDADD) +lex_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +md_test_SOURCES = md_test.c +md_test_OBJECTS = md_test-md_test.$(OBJEXT) +md_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +mem_test_SOURCES = mem_test.c +mem_test_OBJECTS = mem_test.$(OBJEXT) +mem_test_LDADD = $(LDADD) +mem_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +netaddr_test_SOURCES = netaddr_test.c +netaddr_test_OBJECTS = netaddr_test.$(OBJEXT) +netaddr_test_LDADD = $(LDADD) +netaddr_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +am_netmgr_test_OBJECTS = netmgr_test-netmgr_test.$(OBJEXT) +netmgr_test_OBJECTS = $(am_netmgr_test_OBJECTS) +netmgr_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) +parse_test_SOURCES = parse_test.c +parse_test_OBJECTS = parse_test.$(OBJEXT) +parse_test_LDADD = $(LDADD) +parse_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +pool_test_SOURCES = pool_test.c +pool_test_OBJECTS = pool_test.$(OBJEXT) +pool_test_LDADD = $(LDADD) +pool_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +quota_test_SOURCES = quota_test.c +quota_test_OBJECTS = quota_test.$(OBJEXT) +quota_test_LDADD = $(LDADD) +quota_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +radix_test_SOURCES = radix_test.c +radix_test_OBJECTS = radix_test.$(OBJEXT) +radix_test_LDADD = $(LDADD) +radix_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +random_test_SOURCES = random_test.c +random_test_OBJECTS = random_test.$(OBJEXT) +random_test_DEPENDENCIES = $(am__DEPENDENCIES_2) +regex_test_SOURCES = regex_test.c +regex_test_OBJECTS = regex_test.$(OBJEXT) +regex_test_LDADD = $(LDADD) +regex_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +result_test_SOURCES = result_test.c +result_test_OBJECTS = result_test.$(OBJEXT) +result_test_LDADD = $(LDADD) +result_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +safe_test_SOURCES = safe_test.c +safe_test_OBJECTS = safe_test.$(OBJEXT) +safe_test_LDADD = $(LDADD) +safe_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +siphash_test_SOURCES = siphash_test.c +siphash_test_OBJECTS = siphash_test.$(OBJEXT) +siphash_test_LDADD = $(LDADD) +siphash_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +sockaddr_test_SOURCES = sockaddr_test.c +sockaddr_test_OBJECTS = sockaddr_test.$(OBJEXT) +sockaddr_test_LDADD = $(LDADD) +sockaddr_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +stats_test_SOURCES = stats_test.c +stats_test_OBJECTS = stats_test.$(OBJEXT) +stats_test_LDADD = $(LDADD) +stats_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +symtab_test_SOURCES = symtab_test.c +symtab_test_OBJECTS = symtab_test.$(OBJEXT) +symtab_test_LDADD = $(LDADD) +symtab_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +task_test_SOURCES = task_test.c +task_test_OBJECTS = task_test-task_test.$(OBJEXT) +@HAVE_LIBXML2_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@HAVE_JSON_C_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +task_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +taskpool_test_SOURCES = taskpool_test.c +taskpool_test_OBJECTS = taskpool_test.$(OBJEXT) +taskpool_test_LDADD = $(LDADD) +taskpool_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +time_test_SOURCES = time_test.c +time_test_OBJECTS = time_test.$(OBJEXT) +time_test_LDADD = $(LDADD) +time_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +timer_test_SOURCES = timer_test.c +timer_test_OBJECTS = timer_test.$(OBJEXT) +timer_test_LDADD = $(LDADD) +timer_test_DEPENDENCIES = $(LIBISC_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/aes_test.Po \ + ./$(DEPDIR)/buffer_test.Po ./$(DEPDIR)/counter_test.Po \ + ./$(DEPDIR)/crc64_test.Po ./$(DEPDIR)/doh_test-doh_test.Po \ + ./$(DEPDIR)/errno_test.Po ./$(DEPDIR)/file_test.Po \ + ./$(DEPDIR)/hash_test.Po ./$(DEPDIR)/heap_test.Po \ + ./$(DEPDIR)/hmac_test-hmac_test.Po ./$(DEPDIR)/ht_test.Po \ + ./$(DEPDIR)/lex_test.Po ./$(DEPDIR)/md_test-md_test.Po \ + ./$(DEPDIR)/mem_test.Po ./$(DEPDIR)/netaddr_test.Po \ + ./$(DEPDIR)/netmgr_test-netmgr_test.Po \ + ./$(DEPDIR)/parse_test.Po ./$(DEPDIR)/pool_test.Po \ + ./$(DEPDIR)/quota_test.Po ./$(DEPDIR)/radix_test.Po \ + ./$(DEPDIR)/random_test.Po ./$(DEPDIR)/regex_test.Po \ + ./$(DEPDIR)/result_test.Po ./$(DEPDIR)/safe_test.Po \ + ./$(DEPDIR)/siphash_test.Po ./$(DEPDIR)/sockaddr_test.Po \ + ./$(DEPDIR)/stats_test.Po ./$(DEPDIR)/symtab_test.Po \ + ./$(DEPDIR)/task_test-task_test.Po \ + ./$(DEPDIR)/taskpool_test.Po ./$(DEPDIR)/time_test.Po \ + ./$(DEPDIR)/timer_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = aes_test.c buffer_test.c counter_test.c crc64_test.c \ + $(doh_test_SOURCES) errno_test.c file_test.c hash_test.c \ + heap_test.c hmac_test.c ht_test.c lex_test.c md_test.c \ + mem_test.c netaddr_test.c $(netmgr_test_SOURCES) parse_test.c \ + pool_test.c quota_test.c radix_test.c random_test.c \ + regex_test.c result_test.c safe_test.c siphash_test.c \ + sockaddr_test.c stats_test.c symtab_test.c task_test.c \ + taskpool_test.c time_test.c timer_test.c +DIST_SOURCES = aes_test.c buffer_test.c counter_test.c crc64_test.c \ + $(am__doh_test_SOURCES_DIST) errno_test.c file_test.c \ + hash_test.c heap_test.c hmac_test.c ht_test.c lex_test.c \ + md_test.c mem_test.c netaddr_test.c $(netmgr_test_SOURCES) \ + parse_test.c pool_test.c quota_test.c radix_test.c \ + random_test.c regex_test.c result_test.c safe_test.c \ + siphash_test.c sockaddr_test.c stats_test.c symtab_test.c \ + task_test.c taskpool_test.c time_test.c timer_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc $(CMOCKA_CFLAGS) \ + -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBUV_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +@HAVE_LIBNGHTTP2_TRUE@doh_test_CPPFLAGS = \ +@HAVE_LIBNGHTTP2_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_CFLAGS) \ +@HAVE_LIBNGHTTP2_TRUE@ $(OPENSSL_CFLAGS) + +@HAVE_LIBNGHTTP2_TRUE@doh_test_LDADD = \ +@HAVE_LIBNGHTTP2_TRUE@ $(LDADD) \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_LIBS) + +@HAVE_LIBNGHTTP2_TRUE@doh_test_SOURCES = \ +@HAVE_LIBNGHTTP2_TRUE@ doh_test.c \ +@HAVE_LIBNGHTTP2_TRUE@ uv_wrap.h + +hmac_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +hmac_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +md_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +md_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +netmgr_test_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +netmgr_test_SOURCES = \ + netmgr_test.c \ + uv_wrap.h + +random_test_LDADD = \ + $(LDADD) \ + -lm + +task_test_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_3) $(am__append_5) +task_test_LDADD = $(LDADD) $(am__append_4) $(am__append_6) +EXTRA_DIST = testdata +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/isc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/isc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +aes_test$(EXEEXT): $(aes_test_OBJECTS) $(aes_test_DEPENDENCIES) $(EXTRA_aes_test_DEPENDENCIES) + @rm -f aes_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(aes_test_OBJECTS) $(aes_test_LDADD) $(LIBS) + +buffer_test$(EXEEXT): $(buffer_test_OBJECTS) $(buffer_test_DEPENDENCIES) $(EXTRA_buffer_test_DEPENDENCIES) + @rm -f buffer_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(buffer_test_OBJECTS) $(buffer_test_LDADD) $(LIBS) + +counter_test$(EXEEXT): $(counter_test_OBJECTS) $(counter_test_DEPENDENCIES) $(EXTRA_counter_test_DEPENDENCIES) + @rm -f counter_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(counter_test_OBJECTS) $(counter_test_LDADD) $(LIBS) + +crc64_test$(EXEEXT): $(crc64_test_OBJECTS) $(crc64_test_DEPENDENCIES) $(EXTRA_crc64_test_DEPENDENCIES) + @rm -f crc64_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(crc64_test_OBJECTS) $(crc64_test_LDADD) $(LIBS) + +doh_test$(EXEEXT): $(doh_test_OBJECTS) $(doh_test_DEPENDENCIES) $(EXTRA_doh_test_DEPENDENCIES) + @rm -f doh_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(doh_test_OBJECTS) $(doh_test_LDADD) $(LIBS) + +errno_test$(EXEEXT): $(errno_test_OBJECTS) $(errno_test_DEPENDENCIES) $(EXTRA_errno_test_DEPENDENCIES) + @rm -f errno_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(errno_test_OBJECTS) $(errno_test_LDADD) $(LIBS) + +file_test$(EXEEXT): $(file_test_OBJECTS) $(file_test_DEPENDENCIES) $(EXTRA_file_test_DEPENDENCIES) + @rm -f file_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(file_test_OBJECTS) $(file_test_LDADD) $(LIBS) + +hash_test$(EXEEXT): $(hash_test_OBJECTS) $(hash_test_DEPENDENCIES) $(EXTRA_hash_test_DEPENDENCIES) + @rm -f hash_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hash_test_OBJECTS) $(hash_test_LDADD) $(LIBS) + +heap_test$(EXEEXT): $(heap_test_OBJECTS) $(heap_test_DEPENDENCIES) $(EXTRA_heap_test_DEPENDENCIES) + @rm -f heap_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(heap_test_OBJECTS) $(heap_test_LDADD) $(LIBS) + +hmac_test$(EXEEXT): $(hmac_test_OBJECTS) $(hmac_test_DEPENDENCIES) $(EXTRA_hmac_test_DEPENDENCIES) + @rm -f hmac_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(hmac_test_OBJECTS) $(hmac_test_LDADD) $(LIBS) + +ht_test$(EXEEXT): $(ht_test_OBJECTS) $(ht_test_DEPENDENCIES) $(EXTRA_ht_test_DEPENDENCIES) + @rm -f ht_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ht_test_OBJECTS) $(ht_test_LDADD) $(LIBS) + +lex_test$(EXEEXT): $(lex_test_OBJECTS) $(lex_test_DEPENDENCIES) $(EXTRA_lex_test_DEPENDENCIES) + @rm -f lex_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(lex_test_OBJECTS) $(lex_test_LDADD) $(LIBS) + +md_test$(EXEEXT): $(md_test_OBJECTS) $(md_test_DEPENDENCIES) $(EXTRA_md_test_DEPENDENCIES) + @rm -f md_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(md_test_OBJECTS) $(md_test_LDADD) $(LIBS) + +mem_test$(EXEEXT): $(mem_test_OBJECTS) $(mem_test_DEPENDENCIES) $(EXTRA_mem_test_DEPENDENCIES) + @rm -f mem_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mem_test_OBJECTS) $(mem_test_LDADD) $(LIBS) + +netaddr_test$(EXEEXT): $(netaddr_test_OBJECTS) $(netaddr_test_DEPENDENCIES) $(EXTRA_netaddr_test_DEPENDENCIES) + @rm -f netaddr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(netaddr_test_OBJECTS) $(netaddr_test_LDADD) $(LIBS) + +netmgr_test$(EXEEXT): $(netmgr_test_OBJECTS) $(netmgr_test_DEPENDENCIES) $(EXTRA_netmgr_test_DEPENDENCIES) + @rm -f netmgr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(netmgr_test_OBJECTS) $(netmgr_test_LDADD) $(LIBS) + +parse_test$(EXEEXT): $(parse_test_OBJECTS) $(parse_test_DEPENDENCIES) $(EXTRA_parse_test_DEPENDENCIES) + @rm -f parse_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(parse_test_OBJECTS) $(parse_test_LDADD) $(LIBS) + +pool_test$(EXEEXT): $(pool_test_OBJECTS) $(pool_test_DEPENDENCIES) $(EXTRA_pool_test_DEPENDENCIES) + @rm -f pool_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pool_test_OBJECTS) $(pool_test_LDADD) $(LIBS) + +quota_test$(EXEEXT): $(quota_test_OBJECTS) $(quota_test_DEPENDENCIES) $(EXTRA_quota_test_DEPENDENCIES) + @rm -f quota_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(quota_test_OBJECTS) $(quota_test_LDADD) $(LIBS) + +radix_test$(EXEEXT): $(radix_test_OBJECTS) $(radix_test_DEPENDENCIES) $(EXTRA_radix_test_DEPENDENCIES) + @rm -f radix_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(radix_test_OBJECTS) $(radix_test_LDADD) $(LIBS) + +random_test$(EXEEXT): $(random_test_OBJECTS) $(random_test_DEPENDENCIES) $(EXTRA_random_test_DEPENDENCIES) + @rm -f random_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(random_test_OBJECTS) $(random_test_LDADD) $(LIBS) + +regex_test$(EXEEXT): $(regex_test_OBJECTS) $(regex_test_DEPENDENCIES) $(EXTRA_regex_test_DEPENDENCIES) + @rm -f regex_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(regex_test_OBJECTS) $(regex_test_LDADD) $(LIBS) + +result_test$(EXEEXT): $(result_test_OBJECTS) $(result_test_DEPENDENCIES) $(EXTRA_result_test_DEPENDENCIES) + @rm -f result_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(result_test_OBJECTS) $(result_test_LDADD) $(LIBS) + +safe_test$(EXEEXT): $(safe_test_OBJECTS) $(safe_test_DEPENDENCIES) $(EXTRA_safe_test_DEPENDENCIES) + @rm -f safe_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(safe_test_OBJECTS) $(safe_test_LDADD) $(LIBS) + +siphash_test$(EXEEXT): $(siphash_test_OBJECTS) $(siphash_test_DEPENDENCIES) $(EXTRA_siphash_test_DEPENDENCIES) + @rm -f siphash_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(siphash_test_OBJECTS) $(siphash_test_LDADD) $(LIBS) + +sockaddr_test$(EXEEXT): $(sockaddr_test_OBJECTS) $(sockaddr_test_DEPENDENCIES) $(EXTRA_sockaddr_test_DEPENDENCIES) + @rm -f sockaddr_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sockaddr_test_OBJECTS) $(sockaddr_test_LDADD) $(LIBS) + +stats_test$(EXEEXT): $(stats_test_OBJECTS) $(stats_test_DEPENDENCIES) $(EXTRA_stats_test_DEPENDENCIES) + @rm -f stats_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stats_test_OBJECTS) $(stats_test_LDADD) $(LIBS) + +symtab_test$(EXEEXT): $(symtab_test_OBJECTS) $(symtab_test_DEPENDENCIES) $(EXTRA_symtab_test_DEPENDENCIES) + @rm -f symtab_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(symtab_test_OBJECTS) $(symtab_test_LDADD) $(LIBS) + +task_test$(EXEEXT): $(task_test_OBJECTS) $(task_test_DEPENDENCIES) $(EXTRA_task_test_DEPENDENCIES) + @rm -f task_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(task_test_OBJECTS) $(task_test_LDADD) $(LIBS) + +taskpool_test$(EXEEXT): $(taskpool_test_OBJECTS) $(taskpool_test_DEPENDENCIES) $(EXTRA_taskpool_test_DEPENDENCIES) + @rm -f taskpool_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(taskpool_test_OBJECTS) $(taskpool_test_LDADD) $(LIBS) + +time_test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES) $(EXTRA_time_test_DEPENDENCIES) + @rm -f time_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS) + +timer_test$(EXEEXT): $(timer_test_OBJECTS) $(timer_test_DEPENDENCIES) $(EXTRA_timer_test_DEPENDENCIES) + @rm -f timer_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(timer_test_OBJECTS) $(timer_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aes_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/counter_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc64_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doh_test-doh_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errno_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac_test-hmac_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ht_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md_test-md_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netaddr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netmgr_test-netmgr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quota_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radix_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/result_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/siphash_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockaddr_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_test-task_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/taskpool_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +doh_test-doh_test.o: doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT doh_test-doh_test.o -MD -MP -MF $(DEPDIR)/doh_test-doh_test.Tpo -c -o doh_test-doh_test.o `test -f 'doh_test.c' || echo '$(srcdir)/'`doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/doh_test-doh_test.Tpo $(DEPDIR)/doh_test-doh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh_test.c' object='doh_test-doh_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o doh_test-doh_test.o `test -f 'doh_test.c' || echo '$(srcdir)/'`doh_test.c + +doh_test-doh_test.obj: doh_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT doh_test-doh_test.obj -MD -MP -MF $(DEPDIR)/doh_test-doh_test.Tpo -c -o doh_test-doh_test.obj `if test -f 'doh_test.c'; then $(CYGPATH_W) 'doh_test.c'; else $(CYGPATH_W) '$(srcdir)/doh_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/doh_test-doh_test.Tpo $(DEPDIR)/doh_test-doh_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='doh_test.c' object='doh_test-doh_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(doh_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o doh_test-doh_test.obj `if test -f 'doh_test.c'; then $(CYGPATH_W) 'doh_test.c'; else $(CYGPATH_W) '$(srcdir)/doh_test.c'; fi` + +hmac_test-hmac_test.o: hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hmac_test-hmac_test.o -MD -MP -MF $(DEPDIR)/hmac_test-hmac_test.Tpo -c -o hmac_test-hmac_test.o `test -f 'hmac_test.c' || echo '$(srcdir)/'`hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmac_test-hmac_test.Tpo $(DEPDIR)/hmac_test-hmac_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac_test.c' object='hmac_test-hmac_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hmac_test-hmac_test.o `test -f 'hmac_test.c' || echo '$(srcdir)/'`hmac_test.c + +hmac_test-hmac_test.obj: hmac_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hmac_test-hmac_test.obj -MD -MP -MF $(DEPDIR)/hmac_test-hmac_test.Tpo -c -o hmac_test-hmac_test.obj `if test -f 'hmac_test.c'; then $(CYGPATH_W) 'hmac_test.c'; else $(CYGPATH_W) '$(srcdir)/hmac_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hmac_test-hmac_test.Tpo $(DEPDIR)/hmac_test-hmac_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hmac_test.c' object='hmac_test-hmac_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hmac_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hmac_test-hmac_test.obj `if test -f 'hmac_test.c'; then $(CYGPATH_W) 'hmac_test.c'; else $(CYGPATH_W) '$(srcdir)/hmac_test.c'; fi` + +md_test-md_test.o: md_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md_test-md_test.o -MD -MP -MF $(DEPDIR)/md_test-md_test.Tpo -c -o md_test-md_test.o `test -f 'md_test.c' || echo '$(srcdir)/'`md_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md_test-md_test.Tpo $(DEPDIR)/md_test-md_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md_test.c' object='md_test-md_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md_test-md_test.o `test -f 'md_test.c' || echo '$(srcdir)/'`md_test.c + +md_test-md_test.obj: md_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md_test-md_test.obj -MD -MP -MF $(DEPDIR)/md_test-md_test.Tpo -c -o md_test-md_test.obj `if test -f 'md_test.c'; then $(CYGPATH_W) 'md_test.c'; else $(CYGPATH_W) '$(srcdir)/md_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md_test-md_test.Tpo $(DEPDIR)/md_test-md_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md_test.c' object='md_test-md_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(md_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md_test-md_test.obj `if test -f 'md_test.c'; then $(CYGPATH_W) 'md_test.c'; else $(CYGPATH_W) '$(srcdir)/md_test.c'; fi` + +netmgr_test-netmgr_test.o: netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netmgr_test-netmgr_test.o -MD -MP -MF $(DEPDIR)/netmgr_test-netmgr_test.Tpo -c -o netmgr_test-netmgr_test.o `test -f 'netmgr_test.c' || echo '$(srcdir)/'`netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netmgr_test-netmgr_test.Tpo $(DEPDIR)/netmgr_test-netmgr_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netmgr_test.c' object='netmgr_test-netmgr_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netmgr_test-netmgr_test.o `test -f 'netmgr_test.c' || echo '$(srcdir)/'`netmgr_test.c + +netmgr_test-netmgr_test.obj: netmgr_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netmgr_test-netmgr_test.obj -MD -MP -MF $(DEPDIR)/netmgr_test-netmgr_test.Tpo -c -o netmgr_test-netmgr_test.obj `if test -f 'netmgr_test.c'; then $(CYGPATH_W) 'netmgr_test.c'; else $(CYGPATH_W) '$(srcdir)/netmgr_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netmgr_test-netmgr_test.Tpo $(DEPDIR)/netmgr_test-netmgr_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netmgr_test.c' object='netmgr_test-netmgr_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netmgr_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netmgr_test-netmgr_test.obj `if test -f 'netmgr_test.c'; then $(CYGPATH_W) 'netmgr_test.c'; else $(CYGPATH_W) '$(srcdir)/netmgr_test.c'; fi` + +task_test-task_test.o: task_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_test-task_test.o -MD -MP -MF $(DEPDIR)/task_test-task_test.Tpo -c -o task_test-task_test.o `test -f 'task_test.c' || echo '$(srcdir)/'`task_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task_test-task_test.Tpo $(DEPDIR)/task_test-task_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='task_test.c' object='task_test-task_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_test-task_test.o `test -f 'task_test.c' || echo '$(srcdir)/'`task_test.c + +task_test-task_test.obj: task_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task_test-task_test.obj -MD -MP -MF $(DEPDIR)/task_test-task_test.Tpo -c -o task_test-task_test.obj `if test -f 'task_test.c'; then $(CYGPATH_W) 'task_test.c'; else $(CYGPATH_W) '$(srcdir)/task_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task_test-task_test.Tpo $(DEPDIR)/task_test-task_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='task_test.c' object='task_test-task_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(task_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_test-task_test.obj `if test -f 'task_test.c'; then $(CYGPATH_W) 'task_test.c'; else $(CYGPATH_W) '$(srcdir)/task_test.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +aes_test.log: aes_test$(EXEEXT) + @p='aes_test$(EXEEXT)'; \ + b='aes_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +buffer_test.log: buffer_test$(EXEEXT) + @p='buffer_test$(EXEEXT)'; \ + b='buffer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +counter_test.log: counter_test$(EXEEXT) + @p='counter_test$(EXEEXT)'; \ + b='counter_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +crc64_test.log: crc64_test$(EXEEXT) + @p='crc64_test$(EXEEXT)'; \ + b='crc64_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +errno_test.log: errno_test$(EXEEXT) + @p='errno_test$(EXEEXT)'; \ + b='errno_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +file_test.log: file_test$(EXEEXT) + @p='file_test$(EXEEXT)'; \ + b='file_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hash_test.log: hash_test$(EXEEXT) + @p='hash_test$(EXEEXT)'; \ + b='hash_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap_test.log: heap_test$(EXEEXT) + @p='heap_test$(EXEEXT)'; \ + b='heap_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hmac_test.log: hmac_test$(EXEEXT) + @p='hmac_test$(EXEEXT)'; \ + b='hmac_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ht_test.log: ht_test$(EXEEXT) + @p='ht_test$(EXEEXT)'; \ + b='ht_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +lex_test.log: lex_test$(EXEEXT) + @p='lex_test$(EXEEXT)'; \ + b='lex_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +md_test.log: md_test$(EXEEXT) + @p='md_test$(EXEEXT)'; \ + b='md_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +mem_test.log: mem_test$(EXEEXT) + @p='mem_test$(EXEEXT)'; \ + b='mem_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +netaddr_test.log: netaddr_test$(EXEEXT) + @p='netaddr_test$(EXEEXT)'; \ + b='netaddr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +netmgr_test.log: netmgr_test$(EXEEXT) + @p='netmgr_test$(EXEEXT)'; \ + b='netmgr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parse_test.log: parse_test$(EXEEXT) + @p='parse_test$(EXEEXT)'; \ + b='parse_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pool_test.log: pool_test$(EXEEXT) + @p='pool_test$(EXEEXT)'; \ + b='pool_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +quota_test.log: quota_test$(EXEEXT) + @p='quota_test$(EXEEXT)'; \ + b='quota_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +radix_test.log: radix_test$(EXEEXT) + @p='radix_test$(EXEEXT)'; \ + b='radix_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +random_test.log: random_test$(EXEEXT) + @p='random_test$(EXEEXT)'; \ + b='random_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +regex_test.log: regex_test$(EXEEXT) + @p='regex_test$(EXEEXT)'; \ + b='regex_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +result_test.log: result_test$(EXEEXT) + @p='result_test$(EXEEXT)'; \ + b='result_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +safe_test.log: safe_test$(EXEEXT) + @p='safe_test$(EXEEXT)'; \ + b='safe_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +siphash_test.log: siphash_test$(EXEEXT) + @p='siphash_test$(EXEEXT)'; \ + b='siphash_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sockaddr_test.log: sockaddr_test$(EXEEXT) + @p='sockaddr_test$(EXEEXT)'; \ + b='sockaddr_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stats_test.log: stats_test$(EXEEXT) + @p='stats_test$(EXEEXT)'; \ + b='stats_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +symtab_test.log: symtab_test$(EXEEXT) + @p='symtab_test$(EXEEXT)'; \ + b='symtab_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +task_test.log: task_test$(EXEEXT) + @p='task_test$(EXEEXT)'; \ + b='task_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +taskpool_test.log: taskpool_test$(EXEEXT) + @p='taskpool_test$(EXEEXT)'; \ + b='taskpool_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +time_test.log: time_test$(EXEEXT) + @p='time_test$(EXEEXT)'; \ + b='time_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +timer_test.log: timer_test$(EXEEXT) + @p='timer_test$(EXEEXT)'; \ + b='timer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +doh_test.log: doh_test$(EXEEXT) + @p='doh_test$(EXEEXT)'; \ + b='doh_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/aes_test.Po + -rm -f ./$(DEPDIR)/buffer_test.Po + -rm -f ./$(DEPDIR)/counter_test.Po + -rm -f ./$(DEPDIR)/crc64_test.Po + -rm -f ./$(DEPDIR)/doh_test-doh_test.Po + -rm -f ./$(DEPDIR)/errno_test.Po + -rm -f ./$(DEPDIR)/file_test.Po + -rm -f ./$(DEPDIR)/hash_test.Po + -rm -f ./$(DEPDIR)/heap_test.Po + -rm -f ./$(DEPDIR)/hmac_test-hmac_test.Po + -rm -f ./$(DEPDIR)/ht_test.Po + -rm -f ./$(DEPDIR)/lex_test.Po + -rm -f ./$(DEPDIR)/md_test-md_test.Po + -rm -f ./$(DEPDIR)/mem_test.Po + -rm -f ./$(DEPDIR)/netaddr_test.Po + -rm -f ./$(DEPDIR)/netmgr_test-netmgr_test.Po + -rm -f ./$(DEPDIR)/parse_test.Po + -rm -f ./$(DEPDIR)/pool_test.Po + -rm -f ./$(DEPDIR)/quota_test.Po + -rm -f ./$(DEPDIR)/radix_test.Po + -rm -f ./$(DEPDIR)/random_test.Po + -rm -f ./$(DEPDIR)/regex_test.Po + -rm -f ./$(DEPDIR)/result_test.Po + -rm -f ./$(DEPDIR)/safe_test.Po + -rm -f ./$(DEPDIR)/siphash_test.Po + -rm -f ./$(DEPDIR)/sockaddr_test.Po + -rm -f ./$(DEPDIR)/stats_test.Po + -rm -f ./$(DEPDIR)/symtab_test.Po + -rm -f ./$(DEPDIR)/task_test-task_test.Po + -rm -f ./$(DEPDIR)/taskpool_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/timer_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/aes_test.Po + -rm -f ./$(DEPDIR)/buffer_test.Po + -rm -f ./$(DEPDIR)/counter_test.Po + -rm -f ./$(DEPDIR)/crc64_test.Po + -rm -f ./$(DEPDIR)/doh_test-doh_test.Po + -rm -f ./$(DEPDIR)/errno_test.Po + -rm -f ./$(DEPDIR)/file_test.Po + -rm -f ./$(DEPDIR)/hash_test.Po + -rm -f ./$(DEPDIR)/heap_test.Po + -rm -f ./$(DEPDIR)/hmac_test-hmac_test.Po + -rm -f ./$(DEPDIR)/ht_test.Po + -rm -f ./$(DEPDIR)/lex_test.Po + -rm -f ./$(DEPDIR)/md_test-md_test.Po + -rm -f ./$(DEPDIR)/mem_test.Po + -rm -f ./$(DEPDIR)/netaddr_test.Po + -rm -f ./$(DEPDIR)/netmgr_test-netmgr_test.Po + -rm -f ./$(DEPDIR)/parse_test.Po + -rm -f ./$(DEPDIR)/pool_test.Po + -rm -f ./$(DEPDIR)/quota_test.Po + -rm -f ./$(DEPDIR)/radix_test.Po + -rm -f ./$(DEPDIR)/random_test.Po + -rm -f ./$(DEPDIR)/regex_test.Po + -rm -f ./$(DEPDIR)/result_test.Po + -rm -f ./$(DEPDIR)/safe_test.Po + -rm -f ./$(DEPDIR)/siphash_test.Po + -rm -f ./$(DEPDIR)/sockaddr_test.Po + -rm -f ./$(DEPDIR)/stats_test.Po + -rm -f ./$(DEPDIR)/symtab_test.Po + -rm -f ./$(DEPDIR)/task_test-task_test.Po + -rm -f ./$(DEPDIR)/taskpool_test.Po + -rm -f ./$(DEPDIR)/time_test.Po + -rm -f ./$(DEPDIR)/timer_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/isc/aes_test.c b/tests/isc/aes_test.c new file mode 100644 index 0000000..9e9ea22 --- /dev/null +++ b/tests/isc/aes_test.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/aes.h> +#include <isc/buffer.h> +#include <isc/hex.h> +#include <isc/region.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* + * Test data from NIST KAT + */ + +isc_result_t +tohexstr(unsigned char *d, char *out); + +size_t +fromhexstr(const char *in, unsigned char *d); + +unsigned char plaintext[3 * ISC_AES_BLOCK_LENGTH]; +unsigned char ciphertext[ISC_AES_BLOCK_LENGTH]; +char str[2 * ISC_AES_BLOCK_LENGTH + 1]; +unsigned char key[ISC_AES256_KEYLENGTH + 1]; +size_t len; + +isc_result_t +tohexstr(unsigned char *d, char *out) { + isc_buffer_t b; + isc_region_t r; + + isc_buffer_init(&b, out, 2 * ISC_AES_BLOCK_LENGTH + 1); + r.base = d; + r.length = ISC_AES_BLOCK_LENGTH; + return (isc_hex_totext(&r, 0, "", &b)); +} + +size_t +fromhexstr(const char *in, unsigned char *d) { + isc_buffer_t b; + isc_result_t ret; + + isc_buffer_init(&b, d, ISC_AES256_KEYLENGTH + 1); + ret = isc_hex_decodestring(in, &b); + if (ret != ISC_R_SUCCESS) { + return (0); + } + return (isc_buffer_usedlength(&b)); +} + +typedef struct aes_testcase { + const char *key; + const char *input; + const char *result; +} aes_testcase_t; + +/* AES 128 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes128_test) { + aes_testcase_t testcases[] = { /* Test 1 (KAT ECBVarTxt128 #3) */ + { "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "96D9FD5CC4F07441727DF0F33E401A36" }, + /* Test 2 (KAT ECBVarTxt128 #123) */ + { "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "F9B0FDA0C4A898F5B9E6F661C4CE4D07" }, + /* Test 3 (KAT ECBVarKey128 #3) */ + { "F0000000000000000000000000000000", + "00000000000000000000000000000000", + "970014D634E2B7650777E8E84D03CCD8" }, + /* Test 4 (KAT ECBVarKey128 #123) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "41C78C135ED9E98C096640647265DA1E" }, + /* Test 5 (KAT ECBGFSbox128 #3) */ + { "00000000000000000000000000000000", + "6A118A874519E64E9963798A503F1D35", + "DC43BE40BE0E53712F7E2BF5CA707209" }, + /* Test 6 (KAT ECBKeySbox128 #3) */ + { "B6364AC4E1DE1E285EAF144A2415F7A0", + "00000000000000000000000000000000", + "5D9B05578FC944B3CF1CCF0E746CD581" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + UNUSED(state); + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES128_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes128_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +/* AES 192 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes192_test) { + aes_testcase_t testcases[] = { + /* Test 1 (KAT ECBVarTxt192 #3) */ + { "000000000000000000000000000000000000000000000000", + "F0000000000000000000000000000000", + "2A560364CE529EFC21788779568D5555" }, + /* Test 2 (KAT ECBVarTxt192 #123) */ + { "000000000000000000000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "2AABB999F43693175AF65C6C612C46FB" }, + /* Test 3 (KAT ECBVarKey192 #3) */ + { "F00000000000000000000000000000000000000000000000", + "00000000000000000000000000000000", + "180B09F267C45145DB2F826C2582D35C" }, + /* Test 4 (KAT ECBVarKey192 #187) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "EACF1E6C4224EFB38900B185AB1DFD42" }, + /* Test 5 (KAT ECBGFSbox192 #3) */ + { "000000000000000000000000000000000000000000000000", + "51719783D3185A535BD75ADC65071CE1", + "4F354592FF7C8847D2D0870CA9481B7C" }, + /* Test 6 (KAT ECBKeySbox192 #3) */ + { "CD62376D5EBB414917F0C78F05266433DC9192A1EC943300", + "00000000000000000000000000000000", + "7F6C25FF41858561BB62F36492E93C29" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES192_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes192_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +/* AES 256 test vectors */ +ISC_RUN_TEST_IMPL(isc_aes256_test) { + aes_testcase_t testcases[] = { /* Test 1 (KAT ECBVarTxt256 #3) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "F0000000000000000000000000000000", + "7F2C5ECE07A98D8BEE13C51177395FF7" }, + /* Test 2 (KAT ECBVarTxt256 #123) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "7240E524BC51D8C4D440B1BE55D1062C" }, + /* Test 3 (KAT ECBVarKey256 #3) */ + { "F0000000000000000000000000000000" + "00000000000000000000000000000000", + "00000000000000000000000000000000", + "1C777679D50037C79491A94DA76A9A35" }, + /* Test 4 (KAT ECBVarKey256 #251) */ + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", + "00000000000000000000000000000000", + "03720371A04962EAEA0A852E69972858" }, + /* Test 5 (KAT ECBGFSbox256 #3) */ + { "00000000000000000000000000000000" + "00000000000000000000000000000000", + "8A560769D605868AD80D819BDBA03771", + "38F2C7AE10612415D27CA190D27DA8B4" }, + /* Test 6 (KAT ECBKeySbox256 #3) */ + { "984CA75F4EE8D706F46C2D98C0BF4A45" + "F5B00D791C2DFEB191B5ED8E420FD627", + "00000000000000000000000000000000", + "4307456A9E67813B452E15FA8FFFE398" }, + { NULL, NULL, NULL } + }; + + aes_testcase_t *testcase = testcases; + + UNUSED(state); + + while (testcase->key != NULL) { + len = fromhexstr(testcase->key, key); + assert_int_equal(len, ISC_AES256_KEYLENGTH); + len = fromhexstr(testcase->input, plaintext); + assert_int_equal(len, ISC_AES_BLOCK_LENGTH); + isc_aes256_crypt(key, plaintext, ciphertext); + assert_int_equal(tohexstr(ciphertext, str), ISC_R_SUCCESS); + assert_string_equal(str, testcase->result); + + testcase++; + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_aes128_test) +ISC_TEST_ENTRY(isc_aes192_test) +ISC_TEST_ENTRY(isc_aes256_test) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/buffer_test.c b/tests/isc/buffer_test.c new file mode 100644 index 0000000..1c858d3 --- /dev/null +++ b/tests/isc/buffer_test.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/print.h> +#include <isc/region.h> +#include <isc/result.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* reserve space in dynamic buffers */ +ISC_RUN_TEST_IMPL(isc_buffer_reserve) { + isc_result_t result; + isc_buffer_t *b; + + UNUSED(state); + + b = NULL; + isc_buffer_allocate(mctx, &b, 1024); + assert_int_equal(b->length, 1024); + + /* + * 1024 bytes should already be available, so this call does + * nothing. + */ + result = isc_buffer_reserve(&b, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 1024); + + /* + * This call should grow it to 2048 bytes as only 1024 bytes are + * available in the buffer. + */ + result = isc_buffer_reserve(&b, 1025); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 2048); + + /* + * 2048 bytes should already be available, so this call does + * nothing. + */ + result = isc_buffer_reserve(&b, 2000); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 2048); + + /* + * This call should grow it to 4096 bytes as only 2048 bytes are + * available in the buffer. + */ + result = isc_buffer_reserve(&b, 3000); + assert_int_equal(result, ISC_R_SUCCESS); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 4096); + + /* Consume some of the buffer so we can run the next test. */ + isc_buffer_add(b, 4096); + + /* + * This call should fail and leave buffer untouched. + */ + result = isc_buffer_reserve(&b, UINT_MAX); + assert_int_equal(result, ISC_R_NOMEMORY); + assert_true(ISC_BUFFER_VALID(b)); + assert_non_null(b); + assert_int_equal(b->length, 4096); + + isc_buffer_free(&b); +} + +/* dynamic buffer automatic reallocation */ +ISC_RUN_TEST_IMPL(isc_buffer_dynamic) { + isc_buffer_t *b; + size_t last_length = 10; + int i; + + UNUSED(state); + + b = NULL; + isc_buffer_allocate(mctx, &b, last_length); + assert_non_null(b); + assert_int_equal(b->length, last_length); + + isc_buffer_setautorealloc(b, true); + + isc_buffer_putuint8(b, 1); + + for (i = 0; i < 1000; i++) { + isc_buffer_putstr(b, "thisisa24charslongstring"); + } + assert_true(b->length - last_length >= 1000 * 24); + last_length += 1000 * 24; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint8(b, 1); + } + + assert_true(b->length - last_length >= 10000 * 1); + last_length += 10000 * 1; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint16(b, 1); + } + + assert_true(b->length - last_length >= 10000 * 2); + + last_length += 10000 * 2; + for (i = 0; i < 10000; i++) { + isc_buffer_putuint24(b, 1); + } + assert_true(b->length - last_length >= 10000 * 3); + + last_length += 10000 * 3; + + for (i = 0; i < 10000; i++) { + isc_buffer_putuint32(b, 1); + } + assert_true(b->length - last_length >= 10000 * 4); + + isc_buffer_free(&b); +} + +/* copy a region into a buffer */ +ISC_RUN_TEST_IMPL(isc_buffer_copyregion) { + unsigned char data[] = { 0x11, 0x22, 0x33, 0x44 }; + isc_buffer_t *b = NULL; + isc_result_t result; + + isc_region_t r = { + .base = data, + .length = sizeof(data), + }; + + UNUSED(state); + + isc_buffer_allocate(mctx, &b, sizeof(data)); + + /* + * Fill originally allocated buffer space. + */ + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Appending more data to the buffer should fail. + */ + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_NOSPACE); + + /* + * Enable auto reallocation and retry. Appending should now succeed. + */ + isc_buffer_setautorealloc(b, true); + result = isc_buffer_copyregion(b, &r); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_free(&b); +} + +/* sprintf() into a buffer */ +ISC_RUN_TEST_IMPL(isc_buffer_printf) { + unsigned int used, prev_used; + const char *empty_fmt; + isc_result_t result; + isc_buffer_t *b, sb; + char buf[8]; + + UNUSED(state); + + /* + * Prepare a buffer with auto-reallocation enabled. + */ + b = NULL; + isc_buffer_allocate(mctx, &b, 0); + isc_buffer_setautorealloc(b, true); + + /* + * Sanity check. + */ + result = isc_buffer_printf(b, "foo"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(used, 3); + + result = isc_buffer_printf(b, "bar"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(used, 3 + 3); + + /* + * Also check the terminating NULL byte is there, even though it is not + * part of the buffer's used region. + */ + assert_memory_equal(isc_buffer_current(b), "foobar", 7); + + /* + * Skip over data from previous check to prevent failures in previous + * check from affecting this one. + */ + prev_used = used; + isc_buffer_forward(b, prev_used); + + /* + * Some standard usage checks. + */ + isc_buffer_printf(b, "%d", 42); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2); + + isc_buffer_printf(b, "baz%1X", 42); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2 + 5); + + isc_buffer_printf(b, "%6.1f", 42.42f); + used = isc_buffer_usedlength(b); + assert_int_equal(used - prev_used, 2 + 5 + 6); + + /* + * Also check the terminating NULL byte is there, even though it is not + * part of the buffer's used region. + */ + assert_memory_equal(isc_buffer_current(b), "42baz2A 42.4", 14); + + /* + * Check an empty format string is properly handled. + * + * Note: we don't use a string literal for the format string to + * avoid triggering [-Werror=format-zero-length]. + * Note: we have a dummy third argument as some compilers complain + * without it. + */ + prev_used = used; + empty_fmt = ""; + result = isc_buffer_printf(b, empty_fmt, ""); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(b); + assert_int_equal(prev_used, used); + + isc_buffer_free(&b); + + /* + * Check overflow on a static buffer. + */ + isc_buffer_init(&sb, buf, sizeof(buf)); + result = isc_buffer_printf(&sb, "123456"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "789"); + assert_int_equal(result, ISC_R_NOSPACE); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "78"); + assert_int_equal(result, ISC_R_NOSPACE); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 6); + + result = isc_buffer_printf(&sb, "7"); + assert_int_equal(result, ISC_R_SUCCESS); + used = isc_buffer_usedlength(&sb); + assert_int_equal(used, 7); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_buffer_reserve) +ISC_TEST_ENTRY(isc_buffer_dynamic) +ISC_TEST_ENTRY(isc_buffer_copyregion) +ISC_TEST_ENTRY(isc_buffer_printf) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/counter_test.c b/tests/isc/counter_test.c new file mode 100644 index 0000000..dc8dc50 --- /dev/null +++ b/tests/isc/counter_test.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/counter.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test isc_counter object */ +ISC_RUN_TEST_IMPL(isc_counter) { + isc_result_t result; + isc_counter_t *counter = NULL; + int i; + + UNUSED(state); + + result = isc_counter_create(mctx, 0, &counter); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 10; i++) { + result = isc_counter_increment(counter); + assert_int_equal(result, ISC_R_SUCCESS); + } + + assert_int_equal(isc_counter_used(counter), 10); + + isc_counter_setlimit(counter, 15); + for (i = 0; i < 10; i++) { + result = isc_counter_increment(counter); + if (result != ISC_R_SUCCESS) { + break; + } + } + + assert_int_equal(isc_counter_used(counter), 15); + + isc_counter_detach(&counter); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_counter) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/crc64_test.c b/tests/isc/crc64_test.c new file mode 100644 index 0000000..cb96437 --- /dev/null +++ b/tests/isc/crc64_test.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/crc64.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +ISC_RUN_TEST_IMPL(isc_crc64_init) { + uint64_t crc; + + isc_crc64_init(&crc); + assert_int_equal(crc, 0xffffffffffffffffUL); +} + +static void +_crc64(const char *buf, size_t buflen, const char *result, const int repeats) { + uint64_t crc; + + isc_crc64_init(&crc); + assert_int_equal(crc, 0xffffffffffffffffUL); + + for (int i = 0; i < repeats; i++) { + isc_crc64_update(&crc, buf, buflen); + } + + isc_crc64_final(&crc); + + char hex[16 + 1]; + snprintf(hex, sizeof(hex), "%016" PRIX64, crc); + + assert_memory_equal(hex, result, (result ? strlen(result) : 0)); +} + +/* 64-bit cyclic redundancy check */ +ISC_RUN_TEST_IMPL(isc_crc64) { + _crc64(TEST_INPUT(""), "0000000000000000", 1); + _crc64(TEST_INPUT("a"), "CE73F427ACC0A99A", 1); + _crc64(TEST_INPUT("abc"), "048B813AF9F49702", 1); + _crc64(TEST_INPUT("message digest"), "5273F9EA7A357BF4", 1); + _crc64(TEST_INPUT("abcdefghijklmnopqrstuvwxyz"), "59F079F9218BAAA1", 1); + _crc64(TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789"), + "A36DA8F71E78B6FB", 1); + _crc64(TEST_INPUT("123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890"), + "81E5EB73C8E7874A", 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_crc64_init) +ISC_TEST_ENTRY(isc_crc64) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/doh_test.c b/tests/isc/doh_test.c new file mode 100644 index 0000000..090fb8f --- /dev/null +++ b/tests/isc/doh_test.c @@ -0,0 +1,2307 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <uv.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/atomic.h> +#include <isc/buffer.h> +#include <isc/condition.h> +#include <isc/mutex.h> +#include <isc/netmgr.h> +#include <isc/nonce.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/refcount.h> +#include <isc/sockaddr.h> +#include <isc/thread.h> + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#include "netmgr/http.c" +#include "netmgr/netmgr-int.h" +#include "netmgr/uv-compat.c" +#include "netmgr/uv-compat.h" +#include "netmgr_p.h" + +#include <tests/isc.h> + +#define MAX_NM 2 + +static isc_sockaddr_t tcp_listen_addr; + +static uint64_t send_magic = 0; +static uint64_t stop_magic = 0; + +static uv_buf_t send_msg = { .base = (char *)&send_magic, + .len = sizeof(send_magic) }; + +static atomic_int_fast64_t active_cconnects = 0; +static atomic_int_fast64_t nsends = 0; +static atomic_int_fast64_t ssends = 0; +static atomic_int_fast64_t sreads = 0; +static atomic_int_fast64_t csends = 0; +static atomic_int_fast64_t creads = 0; +static atomic_int_fast64_t ctimeouts = 0; +static atomic_int_fast64_t total_sends = 0; + +static atomic_bool was_error = false; + +static bool reuse_supported = true; +static bool noanswer = false; + +static atomic_bool POST = true; + +static atomic_bool slowdown = false; + +static atomic_bool use_TLS = false; +static isc_tlsctx_t *server_tlsctx = NULL; +static isc_tlsctx_t *client_tlsctx = NULL; +static isc_tlsctx_client_session_cache_t *client_sess_cache = NULL; + +static isc_quota_t listener_quota; +static atomic_bool check_listener_quota = false; + +static isc_nm_http_endpoints_t *endpoints = NULL; + +static bool skip_long_tests = false; + +/* Timeout for soft-timeout tests (0.05 seconds) */ +#define T_SOFT 50 + +#define NSENDS 100 +#define NWRITES 10 + +#define CHECK_RANGE_FULL(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v >= atomic_load(&total_sends)); \ + } + +#define CHECK_RANGE_HALF(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v >= atomic_load(&total_sends) / 2); \ + } + +/* Enable this to print values while running tests */ +#undef PRINT_DEBUG +#ifdef PRINT_DEBUG +#define X(v) fprintf(stderr, #v " = %" PRIu64 "\n", atomic_load(&v)) +#else +#define X(v) +#endif + +#define SKIP_IN_CI \ + if (skip_long_tests) { \ + skip(); \ + return; \ + } + +typedef struct csdata { + isc_nm_recv_cb_t reply_cb; + void *cb_arg; + isc_region_t region; +} csdata_t; + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + csdata_t data; + + (void)atomic_fetch_sub(&active_cconnects, 1); + memmove(&data, arg, sizeof(data)); + isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data)); + if (result != ISC_R_SUCCESS) { + goto error; + } + + REQUIRE(VALID_NMHANDLE(handle)); + + result = isc__nm_http_request(handle, &data.region, data.reply_cb, + data.cb_arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); + return; +error: + data.reply_cb(handle, result, NULL, data.cb_arg); + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); + if (result == ISC_R_TOOMANYOPENFILES) { + atomic_store(&slowdown, true); + } else { + atomic_store(&was_error, true); + } +} + +static void +connect_send_request(isc_nm_t *mgr, const char *uri, bool post, + isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg, + bool tls, unsigned int timeout) { + isc_region_t copy; + csdata_t *data = NULL; + isc_tlsctx_t *ctx = NULL; + + copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length), + .length = region->length }; + memmove(copy.base, region->base, region->length); + data = isc_mem_get(mgr->mctx, sizeof(*data)); + *data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy }; + if (tls) { + ctx = client_tlsctx; + } + + isc_nm_httpconnect(mgr, NULL, &tcp_listen_addr, uri, post, + connect_send_cb, data, ctx, client_sess_cache, + timeout, 0); +} + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + isc_result_t result; + socklen_t addrlen = sizeof(*addr); + int fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + isc__nm_closesocket(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + isc__nm_closesocket(fd); + return (r); + } + + result = isc__nm_socket_reuse(fd); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + fprintf(stderr, + "setup_ephemeral_port: isc__nm_socket_reuse(): %s", + isc_result_totext(result)); + close(fd); + return (-1); + } + + result = isc__nm_socket_reuse_lb(fd); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { + fprintf(stderr, + "setup_ephemeral_port: isc__nm_socket_reuse_lb(): %s", + isc_result_totext(result)); + close(fd); + return (-1); + } + if (result == ISC_R_NOTIMPLEMENTED) { + reuse_supported = false; + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + close(fd); + return (r); + } +#endif + + return (fd); +} + +/* Generic */ + +static void +noop_read_cb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, + void *cbarg) { + UNUSED(handle); + UNUSED(result); + UNUSED(region); + UNUSED(cbarg); +} + +thread_local uint8_t tcp_buffer_storage[4096]; +thread_local size_t tcp_buffer_length = 0; + +static int +setup_test(void **state) { + char *env_workers = getenv("ISC_TASK_WORKERS"); + size_t nworkers; + uv_os_sock_t tcp_listen_sock = -1; + isc_nm_t **nm = NULL; + + tcp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM); + if (tcp_listen_sock < 0) { + return (-1); + } + close(tcp_listen_sock); + tcp_listen_sock = -1; + + if (env_workers != NULL) { + workers = atoi(env_workers); + } else { + workers = isc_os_ncpus(); + } + INSIST(workers > 0); + nworkers = ISC_MAX(ISC_MIN(workers, 32), 1); + + if (!reuse_supported || getenv("CI") != NULL) { + skip_long_tests = true; + } + + atomic_store(&total_sends, NSENDS * NWRITES); + atomic_store(&nsends, atomic_load(&total_sends)); + + atomic_store(&csends, 0); + atomic_store(&creads, 0); + atomic_store(&sreads, 0); + atomic_store(&ssends, 0); + atomic_store(&ctimeouts, 0); + atomic_store(&active_cconnects, 0); + + atomic_store(&was_error, false); + + atomic_store(&POST, false); + atomic_store(&use_TLS, false); + + noanswer = false; + + isc_nonce_buf(&send_magic, sizeof(send_magic)); + isc_nonce_buf(&stop_magic, sizeof(stop_magic)); + if (send_magic == stop_magic) { + return (-1); + } + + nm = isc_mem_get(mctx, MAX_NM * sizeof(nm[0])); + for (size_t i = 0; i < MAX_NM; i++) { + isc__netmgr_create(mctx, nworkers, &nm[i]); + assert_non_null(nm[i]); + } + + server_tlsctx = NULL; + isc_tlsctx_createserver(NULL, NULL, &server_tlsctx); + isc_tlsctx_enable_http2server_alpn(server_tlsctx); + client_tlsctx = NULL; + isc_tlsctx_createclient(&client_tlsctx); + isc_tlsctx_enable_http2client_alpn(client_tlsctx); + isc_tlsctx_client_session_cache_create( + mctx, client_tlsctx, + ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, + &client_sess_cache); + + isc_quota_init(&listener_quota, 0); + atomic_store(&check_listener_quota, false); + + INSIST(endpoints == NULL); + endpoints = isc_nm_http_endpoints_new(mctx); + + *state = nm; + + return (0); +} + +static int +teardown_test(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + + for (size_t i = 0; i < MAX_NM; i++) { + isc__netmgr_destroy(&nm[i]); + assert_null(nm[i]); + } + isc_mem_put(mctx, nm, MAX_NM * sizeof(nm[0])); + + if (server_tlsctx != NULL) { + isc_tlsctx_free(&server_tlsctx); + } + if (client_tlsctx != NULL) { + isc_tlsctx_free(&client_tlsctx); + } + + isc_tlsctx_client_session_cache_detach(&client_sess_cache); + + isc_quota_destroy(&listener_quota); + + isc_nm_http_endpoints_detach(&endpoints); + + return (0); +} + +thread_local size_t nwrites = NWRITES; + +static void +sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf, + size_t outbuf_len, const char *append) { + isc_nm_http_makeuri(https, sa, NULL, 0, append, outbuf, outbuf_len); +} + +static isc_quota_t * +init_listener_quota(size_t nthreads) { + isc_quota_t *quotap = NULL; + if (atomic_load(&check_listener_quota)) { + unsigned max_quota = ISC_MAX(nthreads / 2, 1); + isc_quota_max(&listener_quota, max_quota); + quotap = &listener_quota; + } + return (quotap); +} + +static void +doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + assert_non_null(handle); + UNUSED(cbarg); + UNUSED(region); + + if (eresult == ISC_R_SUCCESS) { + (void)atomic_fetch_sub(&nsends, 1); + atomic_fetch_add(&csends, 1); + atomic_fetch_add(&creads, 1); + } else { + /* We failed to connect; try again */ + atomic_store(&was_error, true); + } +} + +static void +doh_reply_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(eresult); + UNUSED(cbarg); + + assert_non_null(handle); + + if (eresult == ISC_R_SUCCESS) { + atomic_fetch_add(&ssends, 1); + } +} + +static void +doh_receive_request_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + UNUSED(cbarg); + assert_non_null(handle); + + if (eresult != ISC_R_SUCCESS) { + atomic_store(&was_error, true); + return; + } + + atomic_fetch_add(&sreads, 1); + + memmove(tcp_buffer_storage + tcp_buffer_length, region->base, + region->length); + tcp_buffer_length += region->length; + + while (tcp_buffer_length >= sizeof(magic)) { + magic = *(uint64_t *)tcp_buffer_storage; + assert_true(magic == stop_magic || magic == send_magic); + + tcp_buffer_length -= sizeof(magic); + memmove(tcp_buffer_storage, tcp_buffer_storage + sizeof(magic), + tcp_buffer_length); + + if (magic == send_magic) { + if (!noanswer) { + isc_nm_send(handle, region, doh_reply_sent_cb, + NULL); + } + return; + } else if (magic == stop_magic) { + /* + * We are done, so we don't send anything back. + * There should be no more packets in the buffer. + */ + assert_int_equal(tcp_buffer_length, 0); + } + } +} + +ISC_RUN_TEST_IMPL(mock_doh_uv_tcp_bind) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +static void +doh_noop(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + + isc__netmgr_shutdown(connect_nm); + + assert_int_equal(0, atomic_load(&csends)); + assert_int_equal(0, atomic_load(&creads)); + assert_int_equal(0, atomic_load(&sreads)); + assert_int_equal(0, atomic_load(&ssends)); +} + +ISC_RUN_TEST_IMPL(doh_noop_POST) { + atomic_store(&POST, true); + doh_noop(state); +} + +ISC_RUN_TEST_IMPL(doh_noop_GET) { + atomic_store(&POST, false); + doh_noop(state); +} + +static void +doh_noresponse(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + noop_read_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(doh_noresponse_POST) { + atomic_store(&POST, true); + doh_noresponse(state); +} + +ISC_RUN_TEST_IMPL(doh_noresponse_GET) { + atomic_store(&POST, false); + doh_noresponse(state); +} + +static void +timeout_query_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + UNUSED(eresult); + UNUSED(cbarg); + + assert_non_null(handle); + + if (eresult == ISC_R_SUCCESS) { + atomic_fetch_add(&csends, 1); + } + + isc_nmhandle_detach(&handle); +} + +static void +timeout_retry_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *arg) { + UNUSED(region); + UNUSED(arg); + + assert_non_null(handle); + + atomic_fetch_add(&ctimeouts, 1); + + if (eresult == ISC_R_TIMEDOUT && atomic_load(&ctimeouts) < 5) { + isc_nmhandle_settimeout(handle, T_SOFT); + return; + } + + isc_nmhandle_detach(&handle); +} + +static void +timeout_request_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isc_nmhandle_t *sendhandle = NULL; + isc_nmhandle_t *readhandle = NULL; + + REQUIRE(VALID_NMHANDLE(handle)); + + if (result != ISC_R_SUCCESS) { + goto error; + } + + isc_nmhandle_attach(handle, &sendhandle); + isc_nm_send(handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + timeout_query_sent_cb, arg); + + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, timeout_retry_cb, NULL); + return; + +error: + atomic_store(&was_error, true); +} + +static void +doh_timeout_recovery(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_tlsctx_t *ctx = atomic_load(&use_TLS) ? server_tlsctx : NULL; + char req_url[256]; + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + + /* + * Shorten all the TCP client timeouts to 0.05 seconds. + * timeout_retry_cb() will give up after five timeouts. + */ + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), + ISC_NM_HTTP_DEFAULT_PATH); + isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url, + atomic_load(&POST), timeout_request_cb, NULL, ctx, + client_sess_cache, T_SOFT, 0); + + /* + * Sleep until sends reaches 5. + */ + for (size_t i = 0; i < 1000; i++) { + if (atomic_load(&ctimeouts) == 5) { + break; + } + isc_test_nap(1); + } + assert_true(atomic_load(&ctimeouts) == 5); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(doh_timeout_recovery_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_timeout_recovery(state); +} + +ISC_RUN_TEST_IMPL(doh_timeout_recovery_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_timeout_recovery(state); +} + +static void +doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + UNUSED(region); + + if (eresult != ISC_R_SUCCESS) { + atomic_store(&was_error, true); + return; + } + + assert_non_null(handle); + + int_fast64_t sends = atomic_fetch_sub(&nsends, 1); + atomic_fetch_add(&csends, 1); + atomic_fetch_add(&creads, 1); + if (sends > 0 && cbarg == NULL) { + size_t i; + for (i = 0; i < NWRITES / 2; i++) { + eresult = isc__nm_http_request( + handle, + &(isc_region_t){ + .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_send_reply_cb, (void *)1); + if (eresult == ISC_R_CANCELED) { + break; + } + assert_true(eresult == ISC_R_SUCCESS); + } + } +} + +static isc_threadresult_t +doh_connect_thread(isc_threadarg_t arg) { + isc_nm_t *connect_nm = (isc_nm_t *)arg; + char req_url[256]; + int64_t sends = atomic_load(&nsends); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + + while (sends > 0) { + /* + * We need to back off and slow down if we start getting + * errors, to prevent a thundering herd problem. + */ + int_fast64_t active = atomic_fetch_add(&active_cconnects, 1); + if (atomic_load(&slowdown) || active > workers) { + isc_test_nap(active - workers); + atomic_store(&slowdown, false); + } + connect_send_request( + connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS), + 30000); + sends = atomic_load(&nsends); + } + + return ((isc_threadresult_t)0); +} + +static void +doh_recv_one(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 1); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, NULL, atomic_load(&use_TLS), + 30000); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + while (atomic_load(&ssends) != 1 || atomic_load(&sreads) != 1 || + atomic_load(&csends) != 1) + { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + assert_int_equal(atomic_load(&csends), 1); + assert_int_equal(atomic_load(&creads), 1); + assert_int_equal(atomic_load(&sreads), 1); + assert_int_equal(atomic_load(&ssends), 1); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_one_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_one(state); +} + +static void +doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result, + void *arg) { + REQUIRE(VALID_NMHANDLE(handle)); + if (result != ISC_R_SUCCESS) { + goto error; + } + + result = isc__nm_http_request( + handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + + result = isc__nm_http_request( + handle, + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + return; +error: + atomic_store(&was_error, true); +} + +static void +doh_recv_two(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_tlsctx_t *ctx = NULL; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, + sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH); + + if (atomic_load(&use_TLS)) { + ctx = client_tlsctx; + } + + isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url, + atomic_load(&POST), doh_connect_send_two_requests_cb, + NULL, ctx, client_sess_cache, 5000, 0); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + while (atomic_load(&ssends) != 2 || atomic_load(&sreads) != 2 || + atomic_load(&csends) != 2) + { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + assert_int_equal(atomic_load(&csends), 2); + assert_int_equal(atomic_load(&creads), 2); + assert_int_equal(atomic_load(&sreads), 2); + assert_int_equal(atomic_load(&ssends), 2); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_two_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_two(state); +} + +static void +doh_recv_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + /* wait for the all responses from the server */ + while (atomic_load(&ssends) < atomic_load(&total_sends)) { + if (atomic_load(&was_error)) { + break; + } + isc_test_nap(1); + } + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&use_TLS, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&use_TLS, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&use_TLS, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&use_TLS, true); + atomic_store(&check_listener_quota, true); + doh_recv_send(state); +} + +static void +doh_recv_half_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc__netmgr_shutdown(connect_nm); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_recv_half_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_recv_half_send(state); +} + +static void +doh_half_recv_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_send(state); +} + +static void +doh_half_recv_half_send(void **state) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); + isc_thread_t threads[32] = { 0 }; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, atomic_load(&total_sends) / 2); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + atomic_load(&use_TLS) ? server_tlsctx : NULL, + endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_create(doh_connect_thread, connect_nm, &threads[i]); + } + + while (atomic_load(&nsends) > 0) { + isc_thread_yield(); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + for (size_t i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST) { + SKIP_IN_CI; + + atomic_store(&POST, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET) { + SKIP_IN_CI; + + atomic_store(&POST, false); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_TLS) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_quota) { + SKIP_IN_CI; + + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_quota) { + SKIP_IN_CI; + + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_POST_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, true); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(doh_half_recv_half_send_GET_TLS_quota) { + SKIP_IN_CI; + + atomic_store(&use_TLS, true); + atomic_store(&POST, false); + atomic_store(&check_listener_quota, true); + doh_half_recv_half_send(state); +} + +/* See: GL #2858, !5319 */ +ISC_RUN_TEST_IMPL(doh_bad_connect_uri) { + isc_nm_t **nm = (isc_nm_t **)*state; + isc_nm_t *listen_nm = nm[0]; + isc_nm_t *connect_nm = nm[1]; + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + char req_url[256]; + isc_quota_t *quotap = init_listener_quota(workers); + + atomic_store(&total_sends, 1); + + atomic_store(&nsends, atomic_load(&total_sends)); + + result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH, + doh_receive_request_cb, NULL, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, + server_tlsctx, endpoints, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * "https://::1:XXXX/dns-query" is a bad URI, it should be + * "https://[::1]:XXXX/dns-query" + */ + (void)snprintf(req_url, sizeof(req_url), "https://::1:%u/%s", + isc_sockaddr_getport(&tcp_listen_addr), + ISC_NM_HTTP_DEFAULT_PATH); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, NULL, true, 30000); + + while (atomic_load(&nsends) > 0) { + if (atomic_load(&was_error)) { + break; + } + isc_thread_yield(); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(total_sends); + X(csends); + X(creads); + X(sreads); + X(ssends); + + /* As we used an ill-formed URI, there ought to be an error. */ + assert_true(atomic_load(&was_error)); + assert_int_equal(atomic_load(&csends), 0); + assert_int_equal(atomic_load(&creads), 0); + assert_int_equal(atomic_load(&sreads), 0); + assert_int_equal(atomic_load(&ssends), 0); +} + +ISC_RUN_TEST_IMPL(doh_parse_GET_query_string) { + UNUSED(state); + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "dns=AAABAAABAAAAAAAAAWE-" + "NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3" + "QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == strlen(str) - 4); + assert_true(memcmp(queryp, str + 4, len) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?dns=AAABAAABAAAAAAAAAWE-" + "NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3" + "QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == strlen(str) - 6); + assert_true(memcmp(queryp, str + 5, len) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123&dns=567"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "567", 3) == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?name1=123&dns=567&name2=123&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "567", 3) == 0); + } + /* complex, but still valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%" + "BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%" + "D0%BD%D0%BD%D1%8F&dns=123&veaction=edit§ion=0"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 3); + assert_true(memcmp(queryp, "123", 3) == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = + "?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%" + "BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%" + "D0%BD%D0%BD%D1%8F&veaction=edit§ion=0"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = ""; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123&&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%12&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 6); + assert_true(memcmp(queryp, "123%12", 6) == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%ZZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%%&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* invalid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%AZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_false(ret); + assert_null(queryp); + assert_true(len == 0); + } + /* valid */ + { + bool ret; + const char *queryp = NULL; + size_t len = 0; + char str[] = "?dns=123%0AZ&"; + + ret = isc__nm_parse_httpquery(str, &queryp, &len); + assert_true(ret); + assert_non_null(queryp); + assert_true(len > 0); + assert_true(len == 7); + assert_true(memcmp(queryp, "123%0AZ", 7) == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_base64url_to_base64) { + UNUSED(state); + char *res; + size_t res_len = 0; + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhc3U"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "PDw_Pz8-Pg"; + char res_test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char test[] = "PDw_Pz8-Pg"; + char res_test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + NULL); + assert_non_null(res); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* invalid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, 0, &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = ""; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg=="; + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the + end */ + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + res_len = 0; + + res = isc__nm_base64url_to_base64(mctx, NULL, 31231, &res_len); + assert_null(res); + assert_true(res_len == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_base64_to_base64url) { + char *res; + size_t res_len = 0; + UNUSED(state); + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy"; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U"; + char test[] = "YW55IGNhcm5hbCBwbGVhc3U="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "YW55IGNhcm5hbCBwbGVhcw"; + char test[] = "YW55IGNhcm5hbCBwbGVhcw=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "PDw_Pz8-Pg"; + char test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_non_null(res); + assert_true(res_len == strlen(res_test)); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* valid */ + { + char res_test[] = "PDw_Pz8-Pg"; + char test[] = "PDw/Pz8+Pg=="; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + NULL); + assert_non_null(res); + assert_true(strcmp(res, res_test) == 0); + isc_mem_free(mctx, res); + } + /* invalid */ + { + char test[] = "YW55IGNhcm5hbCBwbGVhcw"; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, 0, &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = ""; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg=="; + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the + end */ + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, test, strlen(test), + &res_len); + assert_null(res); + assert_true(res_len == 0); + } + /* invalid */ + { + res_len = 0; + + res = isc__nm_base64_to_base64url(mctx, NULL, 31231, &res_len); + assert_null(res); + assert_true(res_len == 0); + } +} + +ISC_RUN_TEST_IMPL(doh_path_validation) { + UNUSED(state); + + assert_true(isc_nm_http_path_isvalid("/")); + assert_true(isc_nm_http_path_isvalid(ISC_NM_HTTP_DEFAULT_PATH)); + assert_false(isc_nm_http_path_isvalid("laaaa")); + assert_false(isc_nm_http_path_isvalid("")); + assert_false(isc_nm_http_path_isvalid("//")); + assert_true(isc_nm_http_path_isvalid("/lala///")); + assert_true(isc_nm_http_path_isvalid("/lalaaaaaa")); + assert_true(isc_nm_http_path_isvalid("/lalaaa/la/la/la")); + assert_true(isc_nm_http_path_isvalid("/la/a")); + assert_true(isc_nm_http_path_isvalid("/la+la")); + assert_true(isc_nm_http_path_isvalid("/la&la/la*la/l-a_/la!/la\'")); + assert_true(isc_nm_http_path_isvalid("/la/(la)/la")); + assert_true(isc_nm_http_path_isvalid("/la,la,la")); + assert_true(isc_nm_http_path_isvalid("/la-'la'-la")); + assert_true(isc_nm_http_path_isvalid("/la:la=la")); + assert_true(isc_nm_http_path_isvalid("/l@l@l@")); + assert_false(isc_nm_http_path_isvalid("/#lala")); + assert_true(isc_nm_http_path_isvalid("/lala;la")); + assert_false( + isc_nm_http_path_isvalid("la&la/laalaala*lala/l-al_a/lal!/")); + assert_true(isc_nm_http_path_isvalid("/Lal/lAla.jpg")); + + /* had to replace ? with ! because it does not verify a query string */ + assert_true(isc_nm_http_path_isvalid("/watch!v=oavMtUWDBTM")); + assert_false(isc_nm_http_path_isvalid("/watch?v=dQw4w9WgXcQ")); + assert_true(isc_nm_http_path_isvalid("/datatracker.ietf.org/doc/html/" + "rfc2616")); + assert_true(isc_nm_http_path_isvalid("/doc/html/rfc8484")); + assert_true(isc_nm_http_path_isvalid("/123")); +} + +ISC_RUN_TEST_IMPL(doh_connect_makeuri) { + struct in_addr localhostv4 = { .s_addr = ntohl(INADDR_LOOPBACK) }; + isc_sockaddr_t sa; + char uri[256]; + UNUSED(state); + + /* Firstly, test URI generation using isc_sockaddr_t */ + isc_sockaddr_fromin(&sa, &localhostv4, 0); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0); + + /* + * The port value should be ignored, because we can get one from + * the isc_sockaddr_t object. + */ + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0); + + /* IPv6 */ + isc_sockaddr_fromin6(&sa, &in6addr_loopback, 0); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0); + + /* + * The port value should be ignored, because we can get one from + * the isc_sockaddr_t object. + */ + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0); + + /* Try to set the port numbers. */ + isc_sockaddr_setport(&sa, 44343); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0); + + isc_sockaddr_setport(&sa, 8080); + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri, + sizeof(uri)); + assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0); + + /* + * Try to make a URI using a hostname and a port number. The + * isc_sockaddr_t object will be ignored. + */ + isc_sockaddr_any(&sa); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, "example.com", 0, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://example.com:443/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, "example.com", 0, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://example.com:80/dns-query", uri) == 0); + + /* Try to set the port numbers. */ + isc_sockaddr_setport(&sa, 443); + uri[0] = '\0'; + isc_nm_http_makeuri(true, &sa, "example.com", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://example.com:44343/dns-query", uri) == 0); + + isc_sockaddr_setport(&sa, 80); + uri[0] = '\0'; + isc_nm_http_makeuri(false, &sa, "example.com", 8080, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://example.com:8080/dns-query", uri) == 0); + + /* IPv4 as the hostname - nothing fancy here */ + uri[0] = '\0'; + isc_nm_http_makeuri(false, NULL, "127.0.0.1", 8080, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("http://127.0.0.1:8080/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(true, NULL, "127.0.0.1", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://127.0.0.1:44343/dns-query", uri) == 0); + + /* + * A peculiar edge case: IPv6 given as the hostname (notice + * the brackets) + */ + uri[0] = '\0'; + isc_nm_http_makeuri(false, NULL, "::1", 8080, ISC_NM_HTTP_DEFAULT_PATH, + uri, sizeof(uri)); + assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0); + + uri[0] = '\0'; + isc_nm_http_makeuri(true, NULL, "[::1]", 44343, + ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri)); + assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(mock_doh_uv_tcp_bind, setup_test, teardown_test) +ISC_TEST_ENTRY(doh_parse_GET_query_string) +ISC_TEST_ENTRY(doh_base64url_to_base64) +ISC_TEST_ENTRY(doh_base64_to_base64url) +ISC_TEST_ENTRY(doh_path_validation) +ISC_TEST_ENTRY(doh_connect_makeuri) +ISC_TEST_ENTRY_CUSTOM(doh_noop_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noop_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noresponse_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_noresponse_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_recv_half_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_TLS, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_TLS, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_TLS, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_GET_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_half_recv_half_send_POST_TLS_quota, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(doh_bad_connect_uri, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/errno_test.c b/tests/isc/errno_test.c new file mode 100644 index 0000000..fbfe56a --- /dev/null +++ b/tests/isc/errno_test.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <errno.h> +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/errno.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +typedef struct { + int err; + isc_result_t result; +} testpair_t; + +testpair_t testpair[] = { { EPERM, ISC_R_NOPERM }, + { ENOENT, ISC_R_FILENOTFOUND }, + { EIO, ISC_R_IOERROR }, + { EBADF, ISC_R_INVALIDFILE }, + { ENOMEM, ISC_R_NOMEMORY }, + { EACCES, ISC_R_NOPERM }, + { EEXIST, ISC_R_FILEEXISTS }, + { ENOTDIR, ISC_R_INVALIDFILE }, + { EINVAL, ISC_R_INVALIDFILE }, + { ENFILE, ISC_R_TOOMANYOPENFILES }, + { EMFILE, ISC_R_TOOMANYOPENFILES }, + { EPIPE, ISC_R_CONNECTIONRESET }, + { ENAMETOOLONG, ISC_R_INVALIDFILE }, + { ELOOP, ISC_R_INVALIDFILE }, +#ifdef EOVERFLOW + { EOVERFLOW, ISC_R_RANGE }, +#endif /* ifdef EOVERFLOW */ +#ifdef EAFNOSUPPORT + { EAFNOSUPPORT, ISC_R_FAMILYNOSUPPORT }, +#endif /* ifdef EAFNOSUPPORT */ +#ifdef EADDRINUSE + { EADDRINUSE, ISC_R_ADDRINUSE }, +#endif /* ifdef EADDRINUSE */ + { EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL }, +#ifdef ENETDOWN + { ENETDOWN, ISC_R_NETDOWN }, +#endif /* ifdef ENETDOWN */ +#ifdef ENETUNREACH + { ENETUNREACH, ISC_R_NETUNREACH }, +#endif /* ifdef ENETUNREACH */ +#ifdef ECONNABORTED + { ECONNABORTED, ISC_R_CONNECTIONRESET }, +#endif /* ifdef ECONNABORTED */ +#ifdef ECONNRESET + { ECONNRESET, ISC_R_CONNECTIONRESET }, +#endif /* ifdef ECONNRESET */ +#ifdef ENOBUFS + { ENOBUFS, ISC_R_NORESOURCES }, +#endif /* ifdef ENOBUFS */ +#ifdef ENOTCONN + { ENOTCONN, ISC_R_NOTCONNECTED }, +#endif /* ifdef ENOTCONN */ +#ifdef ETIMEDOUT + { ETIMEDOUT, ISC_R_TIMEDOUT }, +#endif /* ifdef ETIMEDOUT */ + { ECONNREFUSED, ISC_R_CONNREFUSED }, +#ifdef EHOSTDOWN + { EHOSTDOWN, ISC_R_HOSTDOWN }, +#endif /* ifdef EHOSTDOWN */ +#ifdef EHOSTUNREACH + { EHOSTUNREACH, ISC_R_HOSTUNREACH }, +#endif /* ifdef EHOSTUNREACH */ + { 0, ISC_R_UNEXPECTED } }; + +/* convert errno to ISC result */ +ISC_RUN_TEST_IMPL(isc_errno_toresult) { + isc_result_t result, expect; + size_t i; + + for (i = 0; i < sizeof(testpair) / sizeof(testpair[0]); i++) { + result = isc_errno_toresult(testpair[i].err); + expect = testpair[i].result; + assert_int_equal(result, expect); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_errno_toresult) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/file_test.c b/tests/isc/file_test.c new file mode 100644 index 0000000..6b75ba2 --- /dev/null +++ b/tests/isc/file_test.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <fcntl.h> +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/file.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +#define NAME "internal" +#define SHA "3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f" +#define TRUNC_SHA "3bed2cb3a3acf7b6" + +#define BAD1 "in/internal" +#define BADHASH1 "8bbb97a888791399" + +#define BAD2 "Internal" +#define BADHASH2 "2ea1842b445b0c81" + +#define F(x) "testdata/file/" x ".test" + +static void +touch(const char *filename) { + int fd; + + unlink(filename); + fd = creat(filename, 0644); + if (fd != -1) { + close(fd); + } +} + +/* test sanitized filenames */ +ISC_RUN_TEST_IMPL(isc_file_sanitize) { + isc_result_t result; + char buf[1024]; + + UNUSED(state); + + assert_return_code(chdir(TESTS_DIR), 0); + + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(NAME)), 0); + + touch(F(TRUNC_SHA)); + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(TRUNC_SHA)), 0); + + touch(F(SHA)); + result = isc_file_sanitize("testdata/file", NAME, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(SHA)), 0); + + result = isc_file_sanitize("testdata/file", BAD1, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(BADHASH1)), 0); + + result = isc_file_sanitize("testdata/file", BAD2, "test", buf, 1024); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(strcmp(buf, F(BADHASH2)), 0); + + unlink(F(TRUNC_SHA)); + unlink(F(SHA)); +} + +/* test filename templates */ +ISC_RUN_TEST_IMPL(isc_file_template) { + isc_result_t result; + char buf[1024]; + + UNUSED(state); + + assert_return_code(chdir(TESTS_DIR), 0); + + result = isc_file_template("/absolute/path", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/absolute/file-XXXXXXXX"); + + result = isc_file_template("relative/path", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "relative/file-XXXXXXXX"); + + result = isc_file_template("/trailing/slash/", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/trailing/slash/file-XXXXXXXX"); + + result = isc_file_template("relative/trailing/slash/", "file-XXXXXXXX", + buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "relative/trailing/slash/file-XXXXXXXX"); + + result = isc_file_template("/", "file-XXXXXXXX", buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "/file-XXXXXXXX"); + + result = isc_file_template("noslash", "file-XXXXXXXX", buf, + sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "file-XXXXXXXX"); + + result = isc_file_template(NULL, "file-XXXXXXXX", buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(buf, "file-XXXXXXXX"); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_file_sanitize) +ISC_TEST_ENTRY(isc_file_template) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/hash_test.c b/tests/isc/hash_test.c new file mode 100644 index 0000000..10a8c27 --- /dev/null +++ b/tests/isc/hash_test.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/hash.h> +#include <isc/hex.h> +#include <isc/print.h> +#include <isc/region.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* Hash function test */ +ISC_RUN_TEST_IMPL(isc_hash_function) { + unsigned int h1; + unsigned int h2; + + UNUSED(state); + + /* Immutability of hash function */ + h1 = isc_hash_function(NULL, 0, true); + h2 = isc_hash_function(NULL, 0, true); + + assert_int_equal(h1, h2); + + /* Hash function characteristics */ + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); + + /* Case */ + h1 = isc_hash_function("Hello world", 12, false); + h2 = isc_hash_function("heLLo WorLd", 12, false); + + assert_int_equal(h1, h2); + + /* Unequal */ + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("heLLo WorLd", 12, true); + + assert_int_not_equal(h1, h2); +} + +/* Hash function initializer test */ +ISC_RUN_TEST_IMPL(isc_hash_initializer) { + unsigned int h1; + unsigned int h2; + + UNUSED(state); + + h1 = isc_hash_function("Hello world", 12, true); + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); + + isc_hash_set_initializer(isc_hash_get_initializer()); + + /* Hash value must not change */ + h2 = isc_hash_function("Hello world", 12, true); + + assert_int_equal(h1, h2); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_hash_function) +ISC_TEST_ENTRY(isc_hash_initializer) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/heap_test.c b/tests/isc/heap_test.c new file mode 100644 index 0000000..19e3ba5 --- /dev/null +++ b/tests/isc/heap_test.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/heap.h> +#include <isc/mem.h> +#include <isc/util.h> + +#include <tests/isc.h> + +struct e { + unsigned int value; + unsigned int index; +}; + +static bool +compare(void *p1, void *p2) { + struct e *e1 = p1; + struct e *e2 = p2; + + return (e1->value < e2->value); +} + +static void +idx(void *p, unsigned int i) { + struct e *e = p; + + e->index = i; +} + +/* test isc_heap_delete() */ +ISC_RUN_TEST_IMPL(isc_heap_delete) { + isc_heap_t *heap = NULL; + struct e e1 = { 100, 0 }; + + UNUSED(state); + + isc_heap_create(mctx, compare, idx, 0, &heap); + assert_non_null(heap); + + isc_heap_insert(heap, &e1); + assert_int_equal(e1.index, 1); + + isc_heap_delete(heap, e1.index); + assert_int_equal(e1.index, 0); + + isc_heap_destroy(&heap); + assert_null(heap); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_heap_delete) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/hmac_test.c b/tests/isc/hmac_test.c new file mode 100644 index 0000000..093c6b2 --- /dev/null +++ b/tests/isc/hmac_test.c @@ -0,0 +1,926 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/hex.h> +#include <isc/hmac.h> +#include <isc/region.h> +#include <isc/result.h> + +#include "hmac.c" + +#include <tests/isc.h> + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +static int +_setup(void **state) { + isc_hmac_t *hmac = isc_hmac_new(); + if (hmac == NULL) { + return (-1); + } + *state = hmac; + return (0); +} + +static int +_teardown(void **state) { + if (*state == NULL) { + return (-1); + } + isc_hmac_free(*state); + return (0); +} + +static int +_reset(void **state) { + if (*state == NULL) { + return (-1); + } + if (isc_hmac_reset(*state) != ISC_R_SUCCESS) { + return (-1); + } + return (0); +} + +ISC_RUN_TEST_IMPL(isc_hmac_new) { + UNUSED(state); + + isc_hmac_t *hmac = isc_hmac_new(); + assert_non_null(hmac); + isc_hmac_free(hmac); /* Cleanup */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_free) { + UNUSED(state); + + isc_hmac_t *hmac = isc_hmac_new(); + assert_non_null(hmac); + isc_hmac_free(hmac); /* Test freeing valid message digest context */ + isc_hmac_free(NULL); /* Test freeing NULL argument */ +} + +static void +isc_hmac_test(isc_hmac_t *hmac, const void *key, size_t keylen, + const isc_md_type_t *type, const char *buf, size_t buflen, + const char *result, const size_t repeats) { + isc_result_t res; + + assert_non_null(hmac); + assert_int_equal(isc_hmac_init(hmac, key, keylen, type), ISC_R_SUCCESS); + + for (size_t i = 0; i < repeats; i++) { + assert_int_equal(isc_hmac_update(hmac, + (const unsigned char *)buf, + buflen), + ISC_R_SUCCESS); + } + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen = sizeof(digest); + assert_int_equal(isc_hmac_final(hmac, digest, &digestlen), + ISC_R_SUCCESS); + + char hexdigest[ISC_MAX_MD_SIZE * 2 + 3]; + isc_region_t r = { .base = digest, .length = digestlen }; + isc_buffer_t b; + isc_buffer_init(&b, hexdigest, sizeof(hexdigest)); + + res = isc_hex_totext(&r, 0, "", &b); + + assert_return_code(res, ISC_R_SUCCESS); + + assert_memory_equal(hexdigest, result, (result ? strlen(result) : 0)); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_init) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + expect_assert_failure(isc_hmac_init(NULL, "", 0, ISC_MD_MD5)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, NULL), + ISC_R_NOTIMPLEMENTED); + + expect_assert_failure(isc_hmac_init(hmac, NULL, 0, ISC_MD_MD5)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_MD5), ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA1), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA224), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA256), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA384), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_update) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + /* Uses message digest context initialized in isc_hmac_init_test() */ + expect_assert_failure(isc_hmac_update(NULL, NULL, 0)); + + assert_int_equal(isc_hmac_update(hmac, NULL, 100), ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"", 0), + ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_hmac_reset) { + isc_hmac_t *hmac = *state; +#if 0 + unsigned char digest[ISC_MAX_MD_SIZE] __attribute((unused)); + unsigned int digestlen __attribute((unused)); +#endif /* if 0 */ + + assert_non_null(hmac); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"a", 1), + ISC_R_SUCCESS); + assert_int_equal(isc_hmac_update(hmac, (const unsigned char *)"b", 1), + ISC_R_SUCCESS); + + assert_int_equal(isc_hmac_reset(hmac), ISC_R_SUCCESS); + +#if 0 + /* + * This test would require OpenSSL compiled with mock_assert(), + * so this could be only manually checked that the test will + * segfault when called by hand + */ + expect_assert_failure(isc_hmac_final(hmac, digest, &digestlen)); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_final) { + isc_hmac_t *hmac = *state; + assert_non_null(hmac); + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen = sizeof(digest); + + /* Fail when message digest context is empty */ + expect_assert_failure(isc_hmac_final(NULL, digest, &digestlen)); + /* Fail when output buffer is empty */ + expect_assert_failure(isc_hmac_final(hmac, NULL, &digestlen)); + + assert_int_equal(isc_hmac_init(hmac, "", 0, ISC_MD_SHA512), + ISC_R_SUCCESS); + /* Fail when the digest length pointer is empty */ + expect_assert_failure(isc_hmac_final(hmac, digest, NULL)); +} + +ISC_RUN_TEST_IMPL(isc_hmac_md5) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_MD5, TEST_INPUT(""), + "74E6F7298A9C2D168935F58C001BAD88", 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_MD5, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "9294727A3638BB1C13F48EF8158BFC9D", 1); + + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_MD5, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79" + "\x61\x20\x77\x61\x6e\x74\x20\x66\x6f" + "\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "750C783E6AB0B503EAA86E310A5DB738", 1); + + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "56BE34521D144C88DBB8C733F0E8B3F6", 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_MD5, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "697EAF0ACA3A3AEA3A75164746FFAA79", 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_MD5, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); + /* Test 6 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "AA4AE5E15272D00E95705637CE8A3B55ED402112", + 1); + /* Test 7 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_MD5, + TEST_INPUT("Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data"), + "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91", + 1); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha1) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA1, TEST_INPUT(""), + "FBDB1D1B18AA6C08324B7D64B71FB76370690E1D", 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA1, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "B617318655057264E28BC0B6FB378C8EF146BE00", 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA1, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79", 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "125D7342B9AC11CD91A39AF48AA17B4F63F175D3", 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA1, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "4C9007F4026250C6BC8414F9BF50C86C2D7235DA", 1); +#if 0 + /* Test 5 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA1, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "AA4AE5E15272D00E95705637CE8A3B55ED402112", 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA1, + TEST_INPUT("Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data"), + "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91", 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha224) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA224, TEST_INPUT(""), + "5CE14F72894662213E2748D2A6BA234B74263910CEDDE2F5" + "A9271524", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA224, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA" + "4F53684B22", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA224, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E61480" + "08FD05E44", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA224, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69" + "D1EC8333EA", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA224, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC01" + "2DE7AFEC5A", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA224, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA224, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7" + "273FA6870E", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA224, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95" + "C9F6F565D1", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha256) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA256, TEST_INPUT(""), + "B613679A0814D9EC772F95D778C35FC5FF1697C493715653" + "C6C712144292C5AD", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA256, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833D" + "A726E9376C2E32CFF7", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA256, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "5BDCC146BF60754E6A042426089575C75A003F089D2739" + "839DEC58B964EC3843", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA256, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "773EA91E36800E46854DB8EBD09181A72959098B3EF8C1" + "22D9635514CED565FE", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA256, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8" + "077A2E3FF46729665B", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA256, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA256, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5" + "140546040F0EE37F54", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA256, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713" + "938A7F51535C3A35E2", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha384) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA384, TEST_INPUT(""), + "6C1F2EE938FAD2E24BD91298474382CA218C75DB3D83E114" + "B3D4367776D14D3551289E75E8209CD4B792302840234ADC", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA384, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "AFD03944D84895626B0825F4AB46907F15F9DADBE4101E" + "C682AA034C7CEBC59CFAEA9EA9076EDE7F4AF152" + "E8B2FA9CB6", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA384, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B" + "47E42EC3736322445E8E2240CA5E69E2C78B3239" + "ECFAB21649", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA384, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9F" + "EBE83EF4E55966144B2A5AB39DC13814B94E3AB6" + "E101A34F27", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA384, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "3E8A69B7783C25851933AB6290AF6CA77A998148085000" + "9CC5577C6E1F573B4E6801DD23C4A7D679CCF8A3" + "86C674CFFB", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA384, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA384, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B58" + "8F3CD11F05033AC4C60C2EF6AB4030FE8296248D" + "F163F44952", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA384, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB" + "9ADCCEBB82461E99C5A678CC31E799176D3860E6" + "110C46523E", + 1); +} + +ISC_RUN_TEST_IMPL(isc_hmac_sha512) { + isc_hmac_t *hmac = *state; + + /* Test 0 */ + isc_hmac_test(hmac, TEST_INPUT(""), ISC_MD_SHA512, TEST_INPUT(""), + "B936CEE86C9F87AA5D3C6F2E84CB5A4239A5FE50480A6EC6" + "6B70AB5B1F4AC6730C6C515421B327EC1D69402E53DFB49A" + "D7381EB067B338FD7B0CB22247225D47", + 1); + + /* Test 1 */ + isc_hmac_test(hmac, + TEST_INPUT("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), + ISC_MD_SHA512, + TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"), + "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2" + "787AD0B30545E17CDEDAA833B7D6B8A702038B27" + "4EAEA3F4E4BE9D914EEB61F1702E696C203A126854", + 1); + /* Test 2 */ + isc_hmac_test(hmac, TEST_INPUT("Jefe"), ISC_MD_SHA512, + TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61" + "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20" + "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"), + "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831F" + "D610270CD7EA2505549758BF75C05A994A6D034F" + "65F8F0E6FDCAEAB1A34D4A6B4B636E070A38BCE737", + 1); + /* Test 3 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"), + ISC_MD_SHA512, + TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"), + "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A" + "3655F83E33B2279D39BF3E848279A722C806B485" + "A47E67C807B946A337BEE8942674278859E13292FB", + 1); + /* Test 4 */ + isc_hmac_test(hmac, + TEST_INPUT("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19"), + ISC_MD_SHA512, + TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"), + "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B87" + "2DE76F8050361EE3DBA91CA5C11AA25EB4D67927" + "5CC5788063A5F19741120C4F2DE2ADEBEB10A298DD", + 1); +#if 0 + /* Test 5 -- unimplemented optional functionality */ + isc_hmac_test(hmac, + TEST_INPUT("\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"), + ISC_MD_SHA512, + TEST_INPUT("Test With Truncation"), + "4C1A03424B55E07FE7F27BE1", + 1); +#endif /* if 0 */ + /* Test 6 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA512, + TEST_INPUT("Test Using Larger Than Block-Size Key - " + "Hash Key First"), + "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEE" + "C1121B013783F8F3526B56D037E05F2598BD0FD2" + "215D6A1E5295E64F73F63F0AEC8B915A985D786598", + 1); + /* Test 7 */ + isc_hmac_test(hmac, + TEST_INPUT("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa"), + ISC_MD_SHA512, + TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20" + "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67" + "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20" + "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20" + "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67" + "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c" + "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b" + "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74" + "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65" + "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20" + "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41" + "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68" + "\x6d\x2e"), + "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289" + "865DF5A32D20CDC944B6022CAC3C4982B10D5EEB" + "55C3E4DE15134676FB6DE0446065C97440FA8C6A58", + 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_hmac_new) +ISC_TEST_ENTRY_CUSTOM(isc_hmac_init, _reset, _reset) + +ISC_TEST_ENTRY_CUSTOM(isc_hmac_reset, _reset, _reset) + +ISC_TEST_ENTRY(isc_hmac_md5) +ISC_TEST_ENTRY(isc_hmac_sha1) +ISC_TEST_ENTRY(isc_hmac_sha224) +ISC_TEST_ENTRY(isc_hmac_sha256) +ISC_TEST_ENTRY(isc_hmac_sha384) +ISC_TEST_ENTRY(isc_hmac_sha512) + +ISC_TEST_ENTRY_CUSTOM(isc_hmac_update, _reset, _reset) +ISC_TEST_ENTRY_CUSTOM(isc_hmac_final, _reset, _reset) + +ISC_TEST_ENTRY(isc_hmac_free) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(_setup, _teardown) diff --git a/tests/isc/ht_test.c b/tests/isc/ht_test.c new file mode 100644 index 0000000..89e18f3 --- /dev/null +++ b/tests/isc/ht_test.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/hash.h> +#include <isc/ht.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* INCLUDE LAST */ + +#define mctx __mctx +#include "ht.c" +#undef mctx + +static void +test_ht_full(int bits, uintptr_t count) { + isc_ht_t *ht = NULL; + isc_result_t result; + uintptr_t i; + + isc_ht_init(&ht, mctx, bits, ISC_HT_CASE_SENSITIVE); + assert_non_null(ht); + + for (i = 1; i < count; i++) { + /* + * Note: snprintf() is followed with strlcat() + * to ensure we are always filling the 16 byte key. + */ + unsigned char key[16]; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal((void *)i, (void *)f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_EXISTS); + } + + for (i = 1; i < count; i++) { + char key[64]; + /* + * Note: the key size is now strlen(key) which is bigger + * then the keys added above. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, (const unsigned char *)key, strlen(key), + (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + /* + * Note: case of KEY is now in capitals, + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + char key[64]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, (const unsigned char *)key, + strlen(key), &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(f, (void *)i); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_delete(ht, key, 16); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + /* + * Note: upper case KEY. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + for (i = 1; i < count; i++) { + char key[64]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_delete(ht, (const unsigned char *)key, + strlen(key)); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_ht_find(ht, (const unsigned char *)key, + strlen(key), &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + /* + * Note: case of KEY is now in capitals, + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " KEY of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal((void *)i, (void *)f); + } + + for (i = 1; i < count; i++) { + unsigned char key[16]; + void *f = NULL; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, " key of a raw hashtable!!", sizeof(key)); + result = isc_ht_find(ht, key, 16, &f); + assert_int_equal(result, ISC_R_NOTFOUND); + assert_null(f); + } + + isc_ht_destroy(&ht); + assert_null(ht); +} + +static void +test_ht_iterator(void) { + isc_ht_t *ht = NULL; + isc_result_t result; + isc_ht_iter_t *iter = NULL; + uintptr_t i; + uintptr_t count = 10000; + uint32_t walked; + unsigned char key[16]; + size_t tksize; + + isc_ht_init(&ht, mctx, 16, ISC_HT_CASE_SENSITIVE); + assert_non_null(ht); + for (i = 1; i <= count; i++) { + /* + * Note that the string we're snprintfing is always > 16 bytes + * so we are always filling the key. + */ + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + result = isc_ht_add(ht, key, 16, (void *)i); + assert_int_equal(result, ISC_R_SUCCESS); + } + + walked = 0; + isc_ht_iter_create(ht, &iter); + + for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS; + result = isc_ht_iter_next(iter)) + { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + walked++; + } + assert_int_equal(walked, count); + assert_int_equal(result, ISC_R_NOMORE); + + /* erase odd */ + walked = 0; + result = isc_ht_iter_first(iter); + while (result == ISC_R_SUCCESS) { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + if ((uintptr_t)v % 2 == 0) { + result = isc_ht_iter_delcurrent_next(iter); + } else { + result = isc_ht_iter_next(iter); + } + walked++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, count); + + /* erase even */ + walked = 0; + result = isc_ht_iter_first(iter); + while (result == ISC_R_SUCCESS) { + unsigned char *tkey = NULL; + void *v = NULL; + + isc_ht_iter_current(iter, &v); + isc_ht_iter_currentkey(iter, &tkey, &tksize); + assert_int_equal(tksize, 16); + i = (uintptr_t)v; + snprintf((char *)key, sizeof(key), "%u", (unsigned int)i); + strlcat((char *)key, "key of a raw hashtable!!", sizeof(key)); + assert_memory_equal(key, tkey, 16); + if ((uintptr_t)v % 2 == 1) { + result = isc_ht_iter_delcurrent_next(iter); + } else { + result = isc_ht_iter_next(iter); + } + walked++; + } + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, count / 2); + + walked = 0; + for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS; + result = isc_ht_iter_next(iter)) + { + walked++; + } + + assert_int_equal(result, ISC_R_NOMORE); + assert_int_equal(walked, 0); + + isc_ht_iter_destroy(&iter); + assert_null(iter); + + isc_ht_destroy(&ht); + assert_null(ht); +} + +/* 20 bit, 200K elements test */ +ISC_RUN_TEST_IMPL(isc_ht_20) { + UNUSED(state); + test_ht_full(20, 200000); +} + +/* 8 bit, 20000 elements crowded test */ +ISC_RUN_TEST_IMPL(isc_ht_8) { + UNUSED(state); + test_ht_full(8, 20000); +} + +ISC_RUN_TEST_IMPL(isc_ht_1) { + UNUSED(state); + test_ht_full(1, 100); +} + +/* test hashtable iterator */ + +ISC_RUN_TEST_IMPL(isc_ht_iterator) { + UNUSED(state); + test_ht_iterator(); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(isc_ht_20) +ISC_TEST_ENTRY(isc_ht_8) +ISC_TEST_ENTRY(isc_ht_1) +ISC_TEST_ENTRY(isc_ht_iterator) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/lex_test.c b/tests/isc/lex_test.c new file mode 100644 index 0000000..47a40dd --- /dev/null +++ b/tests/isc/lex_test.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/lex.h> +#include <isc/mem.h> +#include <isc/util.h> + +#include <tests/isc.h> + +#define AS_STR(x) (x).value.as_textregion.base + +/* check handling of 0xff */ +ISC_RUN_TEST_IMPL(lex_0xff) { + isc_result_t result; + isc_lex_t *lex = NULL; + isc_buffer_t death_buf; + isc_token_t token; + + unsigned char death[] = { EOF, 'A' }; + + UNUSED(state); + + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&death_buf, &death[0], sizeof(death)); + isc_buffer_add(&death_buf, sizeof(death)); + + result = isc_lex_openbuffer(lex, &death_buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_lex_destroy(&lex); +} + +/* check setting of source line */ +ISC_RUN_TEST_IMPL(lex_setline) { + isc_result_t result; + isc_lex_t *lex = NULL; + unsigned char text[] = "text\nto\nbe\nprocessed\nby\nlexer"; + isc_buffer_t buf; + isc_token_t token; + unsigned long line; + int i; + + UNUSED(state); + + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&buf, &text[0], sizeof(text)); + isc_buffer_add(&buf, sizeof(text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 6; i++) { + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_SUCCESS); + + line = isc_lex_getsourceline(lex); + assert_int_equal(line, 100U + i); + } + + result = isc_lex_gettoken(lex, 0, &token); + assert_int_equal(result, ISC_R_EOF); + + line = isc_lex_getsourceline(lex); + assert_int_equal(line, 105U); + + isc_lex_destroy(&lex); +} + +static struct { + const char *text; + const char *string_value; + isc_result_t string_result; + isc_tokentype_t string_type; + const char *qstring_value; + isc_result_t qstring_result; + isc_tokentype_t qstring_type; + const char *qvpair_value; + isc_result_t qvpair_result; + isc_tokentype_t qvpair_type; +} parse_tests[] = { + { "", "", ISC_R_SUCCESS, isc_tokentype_eof, "", ISC_R_SUCCESS, + isc_tokentype_eof, "", ISC_R_SUCCESS, isc_tokentype_eof }, + { "1234", "1234", ISC_R_SUCCESS, isc_tokentype_string, "1234", + ISC_R_SUCCESS, isc_tokentype_string, "1234", ISC_R_SUCCESS, + isc_tokentype_string }, + { "1234=", "1234=", ISC_R_SUCCESS, isc_tokentype_string, + "1234=", ISC_R_SUCCESS, isc_tokentype_string, "1234=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "1234=foo", "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=foo", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "1234=\"foo", "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0 }, + { "1234=\"foo\"", "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, + "1234=\"foo\"", ISC_R_SUCCESS, isc_tokentype_string, "1234=foo", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key", "key", ISC_R_SUCCESS, isc_tokentype_string, "key", + ISC_R_SUCCESS, isc_tokentype_string, "key", ISC_R_SUCCESS, + isc_tokentype_string }, + { "\"key=", "\"key=", ISC_R_SUCCESS, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, "\"key=", ISC_R_SUCCESS, + isc_tokentype_vpair }, + { "\"key=\"", "\"key=\"", ISC_R_SUCCESS, isc_tokentype_string, "key=", + ISC_R_SUCCESS, isc_tokentype_qstring, NULL, ISC_R_UNEXPECTEDEND, 0 }, + { "key=\"\"", "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a b\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a b", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\"a\tb\"", "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=a\tb", + ISC_R_SUCCESS, isc_tokentype_qvpair }, + /* double quote not immediately after '=' is not special. */ + { "key=c\"a b\"", "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key=c\"a", ISC_R_SUCCESS, isc_tokentype_string, "key=c\"a", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* remove special meaning for '=' by escaping */ + { "key\\=", "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=", ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a\"", "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a\"", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a\"", + ISC_R_SUCCESS, isc_tokentype_string }, + { "key\\=\"a \"", "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, + "key\\=\"a", ISC_R_SUCCESS, isc_tokentype_string, "key\\=\"a", + ISC_R_SUCCESS, isc_tokentype_string }, + /* vpair with a key of 'key\=' (would need to be deescaped) */ + { "key\\==", "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key\\==\"\"", "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==\"\"", ISC_R_SUCCESS, isc_tokentype_string, + "key\\==", ISC_R_SUCCESS, isc_tokentype_qvpair }, + { "key=\\\\\\\\", "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\\", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\\", + ISC_R_SUCCESS, isc_tokentype_vpair }, + { "key=\\\\\\\"", "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, + "key=\\\\\\\"", ISC_R_SUCCESS, isc_tokentype_string, "key=\\\\\\\"", + ISC_R_SUCCESS, isc_tokentype_vpair }, + /* incomplete escape sequence */ + { "key=\\\"\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, + /* incomplete escape sequence */ + { "key=\\", NULL, ISC_R_UNEXPECTEDEND, isc_tokentype_string, NULL, + ISC_R_UNEXPECTEDEND, 0, NULL, ISC_R_UNEXPECTEDEND, 0 }, +}; + +/*% + * string + */ +ISC_RUN_TEST_IMPL(lex_string) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_string, true); + + assert_int_equal(result, parse_tests[i].string_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].string_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].string_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].string_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +/*% + * qstring + */ +ISC_RUN_TEST_IMPL(lex_qstring) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_qstring, true); + + assert_int_equal(result, parse_tests[i].qstring_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].qstring_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qstring_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].qstring_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +/*% + * keypair is <string>=<qstring>. This has implications double quotes + * in key names. + */ +ISC_RUN_TEST_IMPL(lex_keypair) { + isc_buffer_t buf; + isc_lex_t *lex = NULL; + isc_result_t result; + isc_token_t token; + size_t i; + + UNUSED(state); + + for (i = 0; i < ARRAY_SIZE(parse_tests); i++) { + result = isc_lex_create(mctx, 1024, &lex); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_constinit(&buf, parse_tests[i].text, + strlen(parse_tests[i].text)); + isc_buffer_add(&buf, strlen(parse_tests[i].text)); + + result = isc_lex_openbuffer(lex, &buf); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(&token, 0, sizeof(token)); + result = isc_lex_getmastertoken(lex, &token, + isc_tokentype_qvpair, true); + + assert_int_equal(result, parse_tests[i].qvpair_result); + if (result == ISC_R_SUCCESS) { + switch (token.type) { + case isc_tokentype_string: + case isc_tokentype_qstring: + case isc_tokentype_vpair: + case isc_tokentype_qvpair: + assert_int_equal(token.type, + parse_tests[i].qvpair_type); + assert_string_equal( + AS_STR(token), + parse_tests[i].qvpair_value); + break; + default: + assert_int_equal(token.type, + parse_tests[i].qvpair_type); + break; + } + } + + isc_lex_destroy(&lex); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(lex_0xff) +ISC_TEST_ENTRY(lex_keypair) +ISC_TEST_ENTRY(lex_setline) +ISC_TEST_ENTRY(lex_string) +ISC_TEST_ENTRY(lex_qstring) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/md_test.c b/tests/isc/md_test.c new file mode 100644 index 0000000..aff12e4 --- /dev/null +++ b/tests/isc/md_test.c @@ -0,0 +1,555 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> + +/* For FIPS_mode() */ +#include <openssl/crypto.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/hex.h> +#include <isc/md.h> +#include <isc/region.h> +#include <isc/result.h> + +#include "md.c" + +#include <tests/isc.h> + +#define TEST_INPUT(x) (x), sizeof(x) - 1 + +static int +_setup(void **state) { + isc_md_t *md = isc_md_new(); + if (md == NULL) { + return (-1); + } + *state = md; + return (0); +} + +static int +_teardown(void **state) { + if (*state == NULL) { + return (-1); + } + isc_md_free(*state); + return (0); +} + +static int +_reset(void **state) { + if (*state == NULL) { + return (-1); + } + if (isc_md_reset(*state) != ISC_R_SUCCESS) { + return (-1); + } + return (0); +} + +ISC_RUN_TEST_IMPL(isc_md_new) { + isc_md_t *md = isc_md_new(); + assert_non_null(md); + isc_md_free(md); /* Cleanup */ +} + +ISC_RUN_TEST_IMPL(isc_md_free) { + isc_md_t *md = isc_md_new(); + assert_non_null(md); + isc_md_free(md); /* Test freeing valid message digest context */ + isc_md_free(NULL); /* Test freeing NULL argument */ +} + +static void +isc_md_test(isc_md_t *md, const isc_md_type_t *type, const char *buf, + size_t buflen, const char *result, const size_t repeats) { + isc_result_t res; + + assert_non_null(md); + assert_int_equal(isc_md_init(md, type), ISC_R_SUCCESS); + + for (size_t i = 0; i < repeats; i++) { + assert_int_equal( + isc_md_update(md, (const unsigned char *)buf, buflen), + ISC_R_SUCCESS); + } + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + assert_int_equal(isc_md_final(md, digest, &digestlen), ISC_R_SUCCESS); + + char hexdigest[ISC_MAX_MD_SIZE * 2 + 3]; + isc_region_t r = { .base = digest, .length = digestlen }; + isc_buffer_t b; + isc_buffer_init(&b, hexdigest, sizeof(hexdigest)); + + res = isc_hex_totext(&r, 0, "", &b); + + assert_return_code(res, ISC_R_SUCCESS); + + assert_memory_equal(hexdigest, result, (result ? strlen(result) : 0)); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_init) { + isc_md_t *md = *state; + assert_non_null(md); + + expect_assert_failure(isc_md_init(NULL, ISC_MD_MD5)); + + assert_int_equal(isc_md_init(md, NULL), ISC_R_NOTIMPLEMENTED); + + assert_int_equal(isc_md_init(md, ISC_MD_MD5), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA1), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA224), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA256), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA384), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_update) { + isc_md_t *md = *state; + assert_non_null(md); + + /* Uses message digest context initialized in isc_md_init_test() */ + expect_assert_failure(isc_md_update(NULL, NULL, 0)); + + assert_int_equal(isc_md_update(md, NULL, 100), ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"", 0), + ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_reset) { + isc_md_t *md = *state; +#if 0 + unsigned char digest[ISC_MAX_MD_SIZE] __attribute((unused)); + unsigned int digestlen __attribute((unused)); +#endif /* if 0 */ + + assert_non_null(md); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"a", 1), + ISC_R_SUCCESS); + assert_int_equal(isc_md_update(md, (const unsigned char *)"b", 1), + ISC_R_SUCCESS); + + assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); + +#if 0 + /* + * This test would require OpenSSL compiled with mock_assert(), + * so this could be only manually checked that the test will + * segfault when called by hand + */ + expect_assert_failure(isc_md_final(md,digest,&digestlen)); +#endif /* if 0 */ +} + +ISC_RUN_TEST_IMPL(isc_md_final) { + isc_md_t *md = *state; + assert_non_null(md); + + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + + /* Fail when message digest context is empty */ + expect_assert_failure(isc_md_final(NULL, digest, &digestlen)); + /* Fail when output buffer is empty */ + expect_assert_failure(isc_md_final(md, NULL, &digestlen)); + + assert_int_equal(isc_md_init(md, ISC_MD_SHA512), ISC_R_SUCCESS); + assert_int_equal(isc_md_final(md, digest, NULL), ISC_R_SUCCESS); +} + +ISC_RUN_TEST_IMPL(isc_md_md5) { + isc_md_t *md = *state; + isc_md_test(md, ISC_MD_MD5, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT(""), + "D41D8CD98F00B204E9800998ECF8427E", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("a"), + "0CC175B9C0F1B6A831C399E269772661", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("abc"), + "900150983CD24FB0D6963F7D28E17F72", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("message digest"), + "F96B697D7CB7938D525A2F31AAF161D0", 1); + isc_md_test(md, ISC_MD_MD5, TEST_INPUT("abcdefghijklmnopqrstuvwxyz"), + "C3FCD3D76192E4007DFB496CCA67E13B", 1); + isc_md_test(md, ISC_MD_MD5, + TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789"), + "D174AB98D277D9F5A5611C2C9F419D9F", 1); + isc_md_test(md, ISC_MD_MD5, + TEST_INPUT("123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890"), + "57EDF4A22BE3C955AC49DA2E2107B67A", 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha1) { + isc_md_t *md = *state; + isc_md_test(md, ISC_MD_SHA1, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT(""), + "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", 1); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("abc"), + "A9993E364706816ABA3E25717850C26C9CD0D89D", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijk" + "ljklmklmnlmnomnopnopq"), + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", 1); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("a"), + "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F", 1000000); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("01234567012345670123456701234567"), + "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452", 20); + isc_md_test(md, ISC_MD_SHA1, TEST_INPUT("\x5e"), + "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46" + "\xaa\x55\xfe\x75\x71\x46"), + "82ABFF6605DBE1C17DEF12A394FA22A82B544A35", 1); + isc_md_test(md, ISC_MD_SHA1, + TEST_INPUT("\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b" + "\x4f\xba\x15\xa1\xd5\x9f\x3f\xd8\x4d\x22" + "\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e" + "\xd1\x15\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea" + "\xd2\x44\x21\xde\xd9\xc3\x25\x92\xbd\x57" + "\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a" + "\x84\xd0\xcf\x1f\x7b\xee\xad\x17\x13\xe2" + "\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" + "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83" + "\x6f\xd5\x56\x2a\x56\xca\xb1\xa2\x8e\x81" + "\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8" + "\x6e\x3b\x33\xa1\x08\xb0\x53\x07\xc0\x0a" + "\xff\x14\xa7\x68\xed\x73\x50\x60\x6a\x0f" + "\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57" + "\x7f\x9b\x38\x80\x7c\x7d\x52\x3d\x6d\x79" + "\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" + "\xcd\xbb\xfb"), + "CB0082C8F197D260991BA6A460E76E202BAD27B3", 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha224) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA224, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT(""), + "D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F", + 1); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("abc"), + "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7" + "E36C9DA7", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijklj" + "klmklmnlmnomnopnopq"), + "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B" + "1952522525", + 1); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("a"), + "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2" + "EE4EE7AD67", + 1000000); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("01234567012345670123456701234567"), + "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA" + "0EB7AB8262", + 20); + isc_md_test(md, ISC_MD_SHA224, TEST_INPUT("\x07"), + "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450" + "BEE2AA8C2A", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29" + "\x9d\x6f\x9d\x93\xdf\x62"), + "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC38" + "8E56191DB1", + 1); + isc_md_test(md, ISC_MD_SHA224, + TEST_INPUT("\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52" + "\x06\x22\xd1\xac\x97\xd5\xcd\xbe\x8c\xb3" + "\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba" + "\x09\xab\xc8\x53\x3c\x52\x50\x88\x7a\x43" + "\xbe\xbb\xac\x90\x6c\x2e\x18\x37\xf2\x6b" + "\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89" + "\x6b\x71\x8b\x2a\x38\x3e\xcd\xac\x16\xb9" + "\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74" + "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11" + "\x12\x24\x5f\x48\xee\x47\x0d\x39\x6c\x1e" + "\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee" + "\xa8\x14\xb6\x13\x5e\xca\x54\x39\x2b\xde" + "\xdb\x94\x89\xbc\x9b\x87\x5a\x8b\xaf\x0d" + "\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2" + "\x64\xbc\x07\x9d\x26\x9f\x2c\x0d\x7e\xdd" + "\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c" + "\x87\x82\x73"), + "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E" + "9F20D5C3A4", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha256) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA256, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT(""), + "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B93" + "4CA495991B7852B855", + 1); + + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("abc"), + "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A" + "9CB410FF61F20015AD", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijkljk" + "lmklmnlmnomnopnopq"), + "248D6A61D20638B8E5C026930C3E6039A33CE45964FF21" + "67F6ECEDD419DB06C1", + 1); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("a"), + "CDC76E5C9914FB9281A1C7E284D73E67F1809A48A49720" + "0E046D39CCC7112CD0", + 1000000); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("01234567012345670123456701234567"), + "594847328451BDFA85056225462CC1D867D877FB388DF0" + "CE35F25AB5562BFBB5", + 20); + isc_md_test(md, ISC_MD_SHA256, TEST_INPUT("\x19"), + "68AA2E2EE5DFF96E3355E6C7EE373E3D6A4E17F75F9518" + "D843709C0C9BC3E3D4", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3" + "\x88\x7a\xb2\xcd\x68\x46\x52"), + "175EE69B02BA9B58E2B0A5FD13819CEA573F3940A94F82" + "5128CF4209BEABB4E8", + 1); + isc_md_test(md, ISC_MD_SHA256, + TEST_INPUT("\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1" + "\x2b\x20\x52\x7a\xfe\xf0\x4d\x8a\x05\x69" + "\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76" + "\x00\x00\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08" + "\x3a\xa3\x9d\x81\x0d\xb3\x10\x77\x7d\xab" + "\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32" + "\x5f\x8b\x23\x74\xde\x7a\x4b\x5a\x58\xcb" + "\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" + "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65" + "\x92\xec\xed\xaa\x66\xca\x82\xa2\x9d\x0c" + "\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4" + "\xc0\xa4\x3f\x8d\x79\xa3\x0a\x16\x5c\xba" + "\xbe\x45\x2b\x77\x4b\x9c\x71\x09\xa9\x7d" + "\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc" + "\x10\x6a\xad\x5a\x9f\xdd\x30\x82\x57\x69" + "\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" + "\x3d\x54\xd6"), + "97DBCA7DF46D62C8A422C941DD7E835B8AD3361763F7E9" + "B2D95F4F0DA6E1CCBC", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha384) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA384, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT(""), + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07" + "434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898" + "B95B" + "", + 1); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("abc"), + "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1" + "631A8B605A43FF5BED8086072BA1E7CC2358BAEC" + "A134C825A7", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl" + "fghijklmghijklmnhijklmnoijklmnopjklmnopq" + "klmnopqrlmnopqrsmnopqrstnopqrstu"), + "09330C33F71147E83D192FC782CD1B4753111B173B3B05" + "D22FA08086E3B0F712FCC7C71A557E2DB966C3E9" + "FA91746039", + 1); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("a"), + "9D0E1809716474CB086E834E310A4A1CED149E9C00F248" + "527972CEC5704C2A5B07B8B3DC38ECC4EBAE97DD" + "D87F3D8985", + 1000000); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("01234567012345670123456701234567"), + "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A" + "70BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A" + "0D79FB4596", + 20); + isc_md_test(md, ISC_MD_SHA384, TEST_INPUT("\xb9"), + "BC8089A19007C0B14195F4ECC74094FEC64F01F9092928" + "2C2FB392881578208AD466828B1C6C283D2722CF" + "0AD1AB6938", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1" + "\x0a\x7f\x4e\x08\x59\x17\x39"), + "C9A68443A005812256B8EC76B00516F0DBB74FAB26D665" + "913F194B6FFB0E91EA9967566B58109CBC675CC2" + "08E4C823F7", + 1); + isc_md_test(md, ISC_MD_SHA384, + TEST_INPUT("\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb" + "\x69\x12\xec\x10\xff\xcf\x74\x79\x03\x49" + "\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21" + "\xdb\x0f\x3e\x7d\xc8\x7f\x82\x32\x64\xbb" + "\xe4\x0d\x18\x11\xc9\xea\x20\x61\xe1\xc8" + "\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02" + "\xfc\x3f\x50\x42\xe6\xbf\x58\xcb\xa8\xa2" + "\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" + "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86" + "\x5f\x25\xcc\x22\xb5\xe8\x77\x84\xa1\x2f" + "\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a" + "\x2c\xe6\x56\x5c\xbd\xf1\x3d\xca\x40\x38" + "\x32\xcf\xcb\x0e\x8b\x72\x11\xe8\x3a\xf3" + "\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5" + "\x1c\xc0\x27\xaa\xed\xef\xf8\x5a\xad\x7c" + "\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a" + "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15" + "\x1c\xb9\xbc\x51\x25\xa4\x22\xe9\x41\xde" + "\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd" + "\xd0\x96\x76\x71\x1c\xf3\xdb\x0a\x34\x40" + "\x72\x0e\x16\x15\xc1\xf2\x2f\xbc\x3c\x72" + "\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77" + "\x40\x86\x42\x14\x7e\xd0\x96"), + "4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4A" + "AF38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD2" + "0CFF1288C0", + 1); +} + +ISC_RUN_TEST_IMPL(isc_md_sha512) { + isc_md_t *md = *state; + + isc_md_test(md, ISC_MD_SHA512, NULL, 0, NULL, 0); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT(""), + "CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715" + "DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877E" + "EC2F63B931BD47417A81A538327AF927DA3E", + 1); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("abc"), + "DDAF35A193617ABACC417349AE20413112E6FA4E89A97E" + "A20A9EEEE64B55D39A2192992A274FC1A836BA3C" + "23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl" + "fghijklmghijklmnhijklmnoijklmnopjklmnopq" + "klmnopqrlmnopqrsmnopqrstnopqrstu"), + "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7F" + "A17299AEADB6889018501D289E4900F7E4331B99" + "DEC4B5433AC7D329EEB6DD26545E96E55B874BE909", + 1); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("a"), + "E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044" + "285632A803AFA973EBDE0FF244877EA60A4CB043" + "2CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B", + 1000000); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("01234567012345670123456701234567"), + "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E0" + "24DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF" + "33C765CB510813A39CD5A84C4ACAA64D3F3FB7BAE9", + 20); + isc_md_test(md, ISC_MD_SHA512, TEST_INPUT("\xD0"), + "9992202938E882E73E20F6B69E68A0A7149090423D93C8" + "1BAB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA" + "8306826C4AD6E74CECE9631BFA8A549B4AB3FBBA15", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81" + "\x6e\x9d\x98\xbf\xf0\xa0"), + "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75AC" + "BDD1C153C9828924C3DDEDAAFE669C5FDD0BC66F" + "630F6773988213EB1B16F517AD0DE4B2F0C95C90F8", + 1); + isc_md_test(md, ISC_MD_SHA512, + TEST_INPUT("\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a" + "\x50\x2d\x65\x82\x4e\x31\xa2\x30\x54\x32" + "\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d" + "\xe1\xde\x69\x74\xbf\x49\x54\x69\xfc\x7f" + "\x33\x8f\x80\x54\xd5\x8c\x26\xc4\x93\x60" + "\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d" + "\x03\xe5\x6f\xf2\xf8\x68\x00\x2b\xc3\xe4" + "\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" + "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69" + "\x4f\xcb\xba\xf8\x8d\x95\x19\xe4\xeb\x50" + "\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc" + "\x44\x65\xc8\x82\x1a\xac\xd2\xfe\x15\xab" + "\x49\x81\x16\x4b\xbb\x6d\xc3\x2f\x96\x90" + "\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b" + "\x76\x32\x99\x41\x9c\xc4\x12\x8b\xe9\xa0" + "\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" + "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13" + "\x2e\x9a\x0d\xc6\xd3\xb1\xf8\xb2\x46\xf1" + "\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20" + "\x98\xe8\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f" + "\x47\x07\xfe\x1e\xa1\xa1\x79\x1b\xa2\xf3" + "\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9" + "\x49\xad\x47\xd7\xfb\x40\xd2"), + "C665BEFB36DA189D78822D10528CBF3B12B3EEF7260399" + "09C1A16A270D48719377966B957A878E72058477" + "9A62825C18DA26415E49A7176A894E7510FD1451F5", + 1); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_md_new) + +ISC_TEST_ENTRY_CUSTOM(isc_md_init, _reset, _reset) + +ISC_TEST_ENTRY_CUSTOM(isc_md_reset, _reset, _reset) + +ISC_TEST_ENTRY(isc_md_md5) +ISC_TEST_ENTRY(isc_md_sha1) + +ISC_TEST_ENTRY(isc_md_sha224) +ISC_TEST_ENTRY(isc_md_sha256) +ISC_TEST_ENTRY(isc_md_sha384) +ISC_TEST_ENTRY(isc_md_sha512) + +ISC_TEST_ENTRY_CUSTOM(isc_md_update, _reset, _reset) +ISC_TEST_ENTRY_CUSTOM(isc_md_final, _reset, _reset) + +ISC_TEST_ENTRY(isc_md_free) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(_setup, _teardown) diff --git a/tests/isc/mem_test.c b/tests/isc/mem_test.c new file mode 100644 index 0000000..f2bbdbd --- /dev/null +++ b/tests/isc/mem_test.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <fcntl.h> +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/atomic.h> +#include <isc/file.h> +#include <isc/mem.h> +#include <isc/mutex.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/stdio.h> +#include <isc/thread.h> +#include <isc/time.h> +#include <isc/util.h> + +#include "mem_p.h" + +#include <tests/isc.h> + +#define MP1_FREEMAX 10 +#define MP1_FILLCNT 10 +#define MP1_MAXALLOC 30 + +#define MP2_FREEMAX 25 +#define MP2_FILLCNT 25 + +/* general memory system tests */ +ISC_RUN_TEST_IMPL(isc_mem) { + void *items1[50]; + void *items2[50]; + void *tmp; + isc_mempool_t *mp1 = NULL, *mp2 = NULL; + unsigned int i, j; + int rval; + + UNUSED(state); + + isc_mempool_create(mctx, 24, &mp1); + isc_mempool_create(mctx, 31, &mp2); + + isc_mempool_setfreemax(mp1, MP1_FREEMAX); + isc_mempool_setfillcount(mp1, MP1_FILLCNT); + + /* + * Allocate MP1_MAXALLOC items from the pool. This is our max. + */ + for (i = 0; i < MP1_MAXALLOC; i++) { + items1[i] = isc_mempool_get(mp1); + assert_non_null(items1[i]); + } + + /* + * Free the first 11 items. Verify that there are 10 free items on + * the free list (which is our max). + */ + for (i = 0; i < 11; i++) { + isc_mempool_put(mp1, items1[i]); + items1[i] = NULL; + } + +#if !__SANITIZE_ADDRESS__ + rval = isc_mempool_getfreecount(mp1); + assert_int_equal(rval, 10); +#endif /* !__SANITIZE_ADDRESS__ */ + + rval = isc_mempool_getallocated(mp1); + assert_int_equal(rval, 19); + + /* + * Now, beat up on mp2 for a while. Allocate 50 items, then free + * them, then allocate 50 more, etc. + */ + + isc_mempool_setfreemax(mp2, 25); + isc_mempool_setfillcount(mp2, 25); + + for (j = 0; j < 500000; j++) { + for (i = 0; i < 50; i++) { + items2[i] = isc_mempool_get(mp2); + assert_non_null(items2[i]); + } + for (i = 0; i < 50; i++) { + isc_mempool_put(mp2, items2[i]); + items2[i] = NULL; + } + } + + /* + * Free all the other items and blow away this pool. + */ + for (i = 11; i < MP1_MAXALLOC; i++) { + isc_mempool_put(mp1, items1[i]); + items1[i] = NULL; + } + + isc_mempool_destroy(&mp1); + isc_mempool_destroy(&mp2); + + isc_mempool_create(mctx, 2, &mp1); + + tmp = isc_mempool_get(mp1); + assert_non_null(tmp); + + isc_mempool_put(mp1, tmp); + + isc_mempool_destroy(&mp1); +} + +#if defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) +/* aligned memory system tests */ +ISC_RUN_TEST_IMPL(isc_mem_aligned) { + isc_mem_t *mctx2 = NULL; + void *ptr; + size_t alignment; + uintptr_t aligned; + + UNUSED(state); + + /* Check different alignment sizes up to the page size */ + for (alignment = sizeof(void *); alignment <= 4096; alignment *= 2) { + size_t size = alignment / 2 - 1; + ptr = isc_mem_get_aligned(mctx, size, alignment); + + /* Check if the pointer is properly aligned */ + aligned = (((uintptr_t)ptr / alignment) * alignment); + assert_ptr_equal(aligned, (uintptr_t)ptr); + + /* Check if we can resize to <alignment, 2*alignment> range */ + ptr = isc_mem_reget_aligned(mctx, ptr, size, + size * 2 + alignment, alignment); + + /* Check if the pointer is still properly aligned */ + aligned = (((uintptr_t)ptr / alignment) * alignment); + assert_ptr_equal(aligned, (uintptr_t)ptr); + + isc_mem_put_aligned(mctx, ptr, size * 2 + alignment, alignment); + + /* Check whether isc_mem_putanddetach_detach() also works */ + isc_mem_create(&mctx2); + ptr = isc_mem_get_aligned(mctx2, size, alignment); + isc_mem_putanddetach_aligned(&mctx2, ptr, size, alignment); + } +} +#endif /* defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) */ + +/* test TotalUse calculation */ +ISC_RUN_TEST_IMPL(isc_mem_total) { + isc_mem_t *mctx2 = NULL; + size_t before, after; + ssize_t diff; + int i; + + UNUSED(state); + + /* Local alloc, free */ + mctx2 = NULL; + isc_mem_create(&mctx2); + + before = isc_mem_total(mctx2); + + for (i = 0; i < 100000; i++) { + void *ptr; + + ptr = isc_mem_get(mctx2, 2048); + isc_mem_put(mctx2, ptr, 2048); + } + + after = isc_mem_total(mctx2); + diff = after - before; + + assert_int_equal(diff, (2048) * 100000); + + /* ISC_MEMFLAG_INTERNAL */ + + before = isc_mem_total(mctx); + + for (i = 0; i < 100000; i++) { + void *ptr; + + ptr = isc_mem_get(mctx, 2048); + isc_mem_put(mctx, ptr, 2048); + } + + after = isc_mem_total(mctx); + diff = after - before; + + assert_int_equal(diff, (2048) * 100000); + + isc_mem_destroy(&mctx2); +} + +/* test InUse calculation */ +ISC_RUN_TEST_IMPL(isc_mem_inuse) { + isc_mem_t *mctx2 = NULL; + size_t before, after; + ssize_t diff; + void *ptr; + + UNUSED(state); + + mctx2 = NULL; + isc_mem_create(&mctx2); + + before = isc_mem_inuse(mctx2); + ptr = isc_mem_allocate(mctx2, 1024000); + isc_mem_free(mctx2, ptr); + after = isc_mem_inuse(mctx2); + + diff = after - before; + + assert_int_equal(diff, 0); + + isc_mem_destroy(&mctx2); +} + +ISC_RUN_TEST_IMPL(isc_mem_zeroget) { + uint8_t *data = NULL; + UNUSED(state); + + data = isc_mem_get(mctx, 0); + assert_non_null(data); + isc_mem_put(mctx, data, 0); +} + +#define REGET_INIT_SIZE 1024 +#define REGET_GROW_SIZE 2048 +#define REGET_SHRINK_SIZE 512 + +ISC_RUN_TEST_IMPL(isc_mem_reget) { + uint8_t *data = NULL; + + UNUSED(state); + + /* test that we can reget NULL */ + data = isc_mem_reget(mctx, NULL, 0, REGET_INIT_SIZE); + assert_non_null(data); + isc_mem_put(mctx, data, REGET_INIT_SIZE); + + /* test that we can re-get a zero-length allocation */ + data = isc_mem_get(mctx, 0); + assert_non_null(data); + + data = isc_mem_reget(mctx, data, 0, REGET_INIT_SIZE); + assert_non_null(data); + + for (size_t i = 0; i < REGET_INIT_SIZE; i++) { + data[i] = i % UINT8_MAX; + } + + data = isc_mem_reget(mctx, data, REGET_INIT_SIZE, REGET_GROW_SIZE); + assert_non_null(data); + + for (size_t i = 0; i < REGET_INIT_SIZE; i++) { + assert_int_equal(data[i], i % UINT8_MAX); + } + + for (size_t i = REGET_GROW_SIZE; i > 0; i--) { + data[i - 1] = i % UINT8_MAX; + } + + data = isc_mem_reget(mctx, data, REGET_GROW_SIZE, REGET_SHRINK_SIZE); + assert_non_null(data); + + for (size_t i = REGET_SHRINK_SIZE; i > 0; i--) { + assert_int_equal(data[i - 1], i % UINT8_MAX); + } + + isc_mem_put(mctx, data, REGET_SHRINK_SIZE); +} + +#if ISC_MEM_TRACKLINES + +/* test mem with no flags */ +ISC_RUN_TEST_IMPL(isc_mem_noflags) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p, *q; + FILE *f; + void *ptr; + + result = isc_stdio_open("mem.output", "w", &f); + assert_int_equal(result, ISC_R_SUCCESS); + + UNUSED(state); + + isc_mem_create(&mctx2); + isc_mem_debugging = 0; + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + buf[sizeof(buf) - 1] = 0; + + p = strchr(buf, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + p += 2; + q = strchr(p, '\n'); + assert_non_null(q); + *q = '\0'; + assert_string_equal(p, "None."); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; +} + +/* test mem with record flag */ +ISC_RUN_TEST_IMPL(isc_mem_recordflag) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + + result = isc_stdio_open("mem.output", "w", &f); + assert_int_equal(result, ISC_R_SUCCESS); + + UNUSED(state); + + isc_mem_create(&mctx2); + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + buf[sizeof(buf) - 1] = 0; + + p = strchr(buf, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + assert_memory_equal(p + 2, "ptr ", 4); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_int_equal(strlen(p), 1); +} + +/* test mem with trace flag */ +ISC_RUN_TEST_IMPL(isc_mem_traceflag) { + isc_result_t result; + isc_mem_t *mctx2 = NULL; + char buf[4096], *p; + FILE *f; + void *ptr; + + /* redirect stderr so we can check trace output */ + f = freopen("mem.output", "w", stderr); + assert_non_null(f); + + UNUSED(state); + + isc_mem_create(&mctx2); + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + ptr = isc_mem_get(mctx2, 2048); + assert_non_null(ptr); + isc__mem_printactive(mctx2, f); + isc_mem_put(mctx2, ptr, 2048); + isc_mem_destroy(&mctx2); + isc_stdio_close(f); + + memset(buf, 0, sizeof(buf)); + result = isc_stdio_open("mem.output", "r", &f); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_stdio_read(buf, sizeof(buf), 1, f, NULL); + assert_int_equal(result, ISC_R_EOF); + isc_stdio_close(f); + isc_file_remove("mem.output"); + + /* return stderr to TTY so we can see errors */ + f = freopen("/dev/tty", "w", stderr); + + buf[sizeof(buf) - 1] = 0; + + assert_memory_equal(buf, "add ", 4); + p = strchr(buf, '\n'); + assert_non_null(p); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_in_range(p, 0, buf + sizeof(buf) - 3); + assert_memory_equal(p + 2, "ptr ", 4); + p = strchr(p + 1, '\n'); + assert_non_null(p); + assert_memory_equal(p + 1, "del ", 4); + + isc_mem_debugging = ISC_MEM_DEBUGRECORD; +} +#endif /* if ISC_MEM_TRACKLINES */ + +#if !defined(__SANITIZE_THREAD__) + +#define ITERS 512 +#define NUM_ITEMS 1024 /* 768 */ +#define ITEM_SIZE 65534 + +static atomic_size_t mem_size; + +static isc_threadresult_t +mem_thread(isc_threadarg_t arg) { + isc_mem_t *mctx2 = (isc_mem_t *)arg; + void *items[NUM_ITEMS]; + size_t size = atomic_load(&mem_size); + while (!atomic_compare_exchange_weak(&mem_size, &size, size / 2)) { + ; + } + + for (int i = 0; i < ITERS; i++) { + for (int j = 0; j < NUM_ITEMS; j++) { + items[j] = isc_mem_get(mctx2, size); + } + for (int j = 0; j < NUM_ITEMS; j++) { + isc_mem_put(mctx2, items[j], size); + } + } + + return ((isc_threadresult_t)0); +} + +ISC_RUN_TEST_IMPL(isc_mem_benchmark) { + int nthreads = ISC_MAX(ISC_MIN(isc_os_ncpus(), 32), 1); + isc_thread_t threads[32]; + isc_time_t ts1, ts2; + double t; + isc_result_t result; + + UNUSED(state); + + atomic_init(&mem_size, ITEM_SIZE); + + result = isc_time_now(&ts1); + assert_int_equal(result, ISC_R_SUCCESS); + + for (int i = 0; i < nthreads; i++) { + isc_thread_create(mem_thread, mctx, &threads[i]); + } + for (int i = 0; i < nthreads; i++) { + isc_thread_join(threads[i], NULL); + } + + result = isc_time_now(&ts2); + assert_int_equal(result, ISC_R_SUCCESS); + + t = isc_time_microdiff(&ts2, &ts1); + + printf("[ TIME ] isc_mem_benchmark: " + "%d isc_mem_{get,put} calls, %f seconds, %f " + "calls/second\n", + nthreads * ITERS * NUM_ITEMS, t / 1000000.0, + (nthreads * ITERS * NUM_ITEMS) / (t / 1000000.0)); +} + +#endif /* __SANITIZE_THREAD */ + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_mem) +#if defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) +ISC_TEST_ENTRY(isc_mem_aligned) +#endif /* defined(HAVE_MALLOC_NP_H) || defined(HAVE_JEMALLOC) */ +ISC_TEST_ENTRY(isc_mem_total) +ISC_TEST_ENTRY(isc_mem_inuse) +ISC_TEST_ENTRY(isc_mem_zeroget) +ISC_TEST_ENTRY(isc_mem_reget) + +#if !defined(__SANITIZE_THREAD__) +ISC_TEST_ENTRY(isc_mem_benchmark) +#endif /* __SANITIZE_THREAD__ */ +#if ISC_MEM_TRACKLINES +ISC_TEST_ENTRY(isc_mem_noflags) +ISC_TEST_ENTRY(isc_mem_recordflag) +/* + * traceflag_test closes stderr, which causes weird + * side effects for any next test trying to use libuv. + * This test has to be the last one to avoid problems. + */ +ISC_TEST_ENTRY(isc_mem_traceflag) +#endif /* if ISC_MEM_TRACKLINES */ + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/netaddr_test.c b/tests/isc/netaddr_test.c new file mode 100644 index 0000000..2394e11 --- /dev/null +++ b/tests/isc/netaddr_test.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/netaddr.h> +#include <isc/sockaddr.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test isc_netaddr_isnetzero() */ +ISC_RUN_TEST_IMPL(netaddr_isnetzero) { + unsigned int i; + struct in_addr ina; + struct { + const char *address; + bool expect; + } tests[] = { { "0.0.0.0", true }, { "0.0.0.1", true }, + { "0.0.1.2", true }, { "0.1.2.3", true }, + { "10.0.0.0", false }, { "10.9.0.0", false }, + { "10.9.8.0", false }, { "10.9.8.7", false }, + { "127.0.0.0", false }, { "127.0.0.1", false } }; + isc_netaddr_t netaddr; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + bool result; + ina.s_addr = inet_addr(tests[i].address); + isc_netaddr_fromin(&netaddr, &ina); + result = isc_netaddr_isnetzero(&netaddr); + assert_int_equal(result, tests[i].expect); + } +} + +/* test isc_netaddr_masktoprefixlen() calculates correct prefix lengths */ +ISC_RUN_TEST_IMPL(netaddr_masktoprefixlen) { + struct in_addr na_a; + struct in_addr na_b; + struct in_addr na_c; + struct in_addr na_d; + isc_netaddr_t ina_a; + isc_netaddr_t ina_b; + isc_netaddr_t ina_c; + isc_netaddr_t ina_d; + unsigned int plen; + + UNUSED(state); + + assert_true(inet_pton(AF_INET, "0.0.0.0", &na_a) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.254", &na_b) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.255", &na_c) >= 0); + assert_true(inet_pton(AF_INET, "255.255.255.0", &na_d) >= 0); + + isc_netaddr_fromin(&ina_a, &na_a); + isc_netaddr_fromin(&ina_b, &na_b); + isc_netaddr_fromin(&ina_c, &na_c); + isc_netaddr_fromin(&ina_d, &na_d); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_a, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 0); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_b, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 31); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_c, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 32); + + assert_int_equal(isc_netaddr_masktoprefixlen(&ina_d, &plen), + ISC_R_SUCCESS); + assert_int_equal(plen, 24); +} + +/* check multicast addresses are detected properly */ +ISC_RUN_TEST_IMPL(netaddr_multicast) { + unsigned int i; + struct { + int family; + const char *addr; + bool is_multicast; + } tests[] = { + { AF_INET, "1.2.3.4", false }, { AF_INET, "4.3.2.1", false }, + { AF_INET, "224.1.1.1", true }, { AF_INET, "1.1.1.244", false }, + { AF_INET6, "::1", false }, { AF_INET6, "ff02::1", true } + }; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + isc_netaddr_t na; + struct in_addr in; + struct in6_addr in6; + int r; + + if (tests[i].family == AF_INET) { + r = inet_pton(AF_INET, tests[i].addr, + (unsigned char *)&in); + assert_int_equal(r, 1); + isc_netaddr_fromin(&na, &in); + } else { + r = inet_pton(AF_INET6, tests[i].addr, + (unsigned char *)&in6); + assert_int_equal(r, 1); + isc_netaddr_fromin6(&na, &in6); + } + + assert_int_equal(isc_netaddr_ismulticast(&na), + tests[i].is_multicast); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(netaddr_isnetzero) +ISC_TEST_ENTRY(netaddr_masktoprefixlen) +ISC_TEST_ENTRY(netaddr_multicast) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/netmgr_test.c b/tests/isc/netmgr_test.c new file mode 100644 index 0000000..a20db6b --- /dev/null +++ b/tests/isc/netmgr_test.c @@ -0,0 +1,2897 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> +#include <uv.h> + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include <openssl/err.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/nonce.h> +#include <isc/os.h> +#include <isc/quota.h> +#include <isc/refcount.h> +#include <isc/sockaddr.h> +#include <isc/thread.h> +#include <isc/tls.h> +#include <isc/util.h> + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include "netmgr/netmgr-int.h" +#include "netmgr/udp.c" +#include "netmgr/uv-compat.c" +#include "netmgr/uv-compat.h" +#include "netmgr_p.h" +#pragma GCC diagnostic pop + +#include <tests/isc.h> + +typedef void (*stream_connect_function)(isc_nm_t *nm); + +static void +connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg); +static void +connect_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg); + +isc_nm_t *listen_nm = NULL; +isc_nm_t *connect_nm = NULL; + +static isc_sockaddr_t udp_listen_addr; +static isc_sockaddr_t udp_connect_addr; + +static isc_sockaddr_t tcp_listen_addr; +static isc_sockaddr_t tcp_connect_addr; +static isc_tlsctx_t *tcp_listen_tlsctx = NULL; +static isc_tlsctx_t *tcp_connect_tlsctx = NULL; +static isc_tlsctx_client_session_cache_t *tcp_tlsctx_client_sess_cache = NULL; + +static uint64_t send_magic = 0; +static uint64_t stop_magic = 0; + +static isc_region_t send_msg = { .base = (unsigned char *)&send_magic, + .length = sizeof(send_magic) }; + +static isc_region_t stop_msg = { .base = (unsigned char *)&stop_magic, + .length = sizeof(stop_magic) }; + +static atomic_bool do_send = false; + +static atomic_int_fast64_t nsends; +static int_fast64_t esends; /* expected sends */ + +static atomic_int_fast64_t ssends = 0; +static atomic_int_fast64_t sreads = 0; +static atomic_int_fast64_t saccepts = 0; + +static atomic_int_fast64_t cconnects = 0; +static atomic_int_fast64_t csends = 0; +static atomic_int_fast64_t creads = 0; +static atomic_int_fast64_t ctimeouts = 0; + +static isc_refcount_t active_cconnects; +static isc_refcount_t active_csends; +static isc_refcount_t active_creads; +static isc_refcount_t active_ssends; +static isc_refcount_t active_sreads; + +static isc_quota_t listener_quota; +static atomic_bool check_listener_quota; + +static bool skip_long_tests = false; + +static bool allow_send_back = false; +static bool noanswer = false; +static bool stream_use_TLS = false; + +static isc_nm_recv_cb_t connect_readcb = NULL; + +#define SKIP_IN_CI \ + if (skip_long_tests) { \ + skip(); \ + return; \ + } + +#define NSENDS 100 + +/* Timeout for soft-timeout tests (0.05 seconds) */ +#define T_SOFT 50 + +/* Timeouts in miliseconds */ +#define T_INIT 120 * 1000 +#define T_IDLE 120 * 1000 +#define T_KEEPALIVE 120 * 1000 +#define T_ADVERTISED 120 * 1000 +#define T_CONNECT 30 * 1000 + +/* Wait for 1 second (1000 milliseconds) */ +#define WAIT_REPEATS 1000 +#define T_WAIT 1 /* 1 millisecond */ + +#define WAIT_FOR(v, op, val) \ + { \ + X(v); \ + int_fast64_t __r = WAIT_REPEATS; \ + int_fast64_t __o = 0; \ + do { \ + int_fast64_t __l = atomic_load(&v); \ + if (__l op val) { \ + break; \ + }; \ + if (__o == __l) { \ + __r--; \ + } else { \ + __r = WAIT_REPEATS; \ + } \ + __o = __l; \ + isc_test_nap(T_WAIT); \ + } while (__r > 0); \ + X(v); \ + P(__r); \ + assert_true(atomic_load(&v) op val); \ + } + +#define WAIT_FOR_EQ(v, val) WAIT_FOR(v, ==, val) +#define WAIT_FOR_NE(v, val) WAIT_FOR(v, !=, val) +#define WAIT_FOR_LE(v, val) WAIT_FOR(v, <=, val) +#define WAIT_FOR_LT(v, val) WAIT_FOR(v, <, val) +#define WAIT_FOR_GE(v, val) WAIT_FOR(v, >=, val) +#define WAIT_FOR_GT(v, val) WAIT_FOR(v, >, val) + +#define DONE() atomic_store(&do_send, false); + +#define CHECK_RANGE_FULL(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v > 1); \ + } + +#define CHECK_RANGE_HALF(v) \ + { \ + int __v = atomic_load(&v); \ + assert_true(__v > 1); \ + } + +/* Enable this to print values while running tests */ +#undef PRINT_DEBUG +#ifdef PRINT_DEBUG +#define X(v) \ + fprintf(stderr, "%s:%s:%d:%s = %" PRId64 "\n", __func__, __FILE__, \ + __LINE__, #v, atomic_load(&v)) +#define P(v) fprintf(stderr, #v " = %" PRId64 "\n", v) +#define F() \ + fprintf(stderr, "%s(%p, %s, %p)\n", __func__, handle, \ + isc_result_totext(eresult), cbarg) +#else +#define X(v) +#define P(v) +#define F() +#endif + +#define atomic_assert_int_eq(val, exp) assert_int_equal(atomic_load(&val), exp) +#define atomic_assert_int_ne(val, exp) \ + assert_int_not_equal(atomic_load(&val), exp) +#define atomic_assert_int_le(val, exp) assert_true(atomic_load(&val) <= exp) +#define atomic_assert_int_lt(val, exp) assert_true(atomic_load(&val) > exp) +#define atomic_assert_int_ge(val, exp) assert_true(atomic_load(&val) >= exp) +#define atomic_assert_int_gt(val, exp) assert_true(atomic_load(&val) > exp) + +static int +setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { + socklen_t addrlen = sizeof(*addr); + uv_os_sock_t fd; + int r; + + isc_sockaddr_fromin6(addr, &in6addr_loopback, 0); + + fd = socket(AF_INET6, family, 0); + if (fd < 0) { + perror("setup_ephemeral_port: socket()"); + return (-1); + } + + r = bind(fd, (const struct sockaddr *)&addr->type.sa, + sizeof(addr->type.sin6)); + if (r != 0) { + perror("setup_ephemeral_port: bind()"); + isc__nm_closesocket(fd); + return (r); + } + + r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen); + if (r != 0) { + perror("setup_ephemeral_port: getsockname()"); + isc__nm_closesocket(fd); + return (r); + } + +#if IPV6_RECVERR +#define setsockopt_on(socket, level, name) \ + setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) + + r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR); + if (r != 0) { + perror("setup_ephemeral_port"); + isc__nm_closesocket(fd); + return (r); + } +#endif + + return (fd); +} + +static int +setup_test(void **state __attribute__((unused))) { + char *env_workers = getenv("ISC_TASK_WORKERS"); + uv_os_sock_t tcp_listen_sock = -1; + uv_os_sock_t udp_listen_sock = -1; + size_t nworkers; + + if (env_workers != NULL) { + workers = atoi(env_workers); + } else { + workers = isc_os_ncpus(); + } + INSIST(workers > 0); + nworkers = ISC_MAX(ISC_MIN(workers, 32), 1); + + if (getenv("CI") != NULL && getenv("CI_ENABLE_ALL_TESTS") == NULL) { + skip_long_tests = true; + esends = nworkers; + } else { + esends = NSENDS * nworkers; + } + + udp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0); + + udp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + udp_listen_sock = setup_ephemeral_port(&udp_listen_addr, SOCK_DGRAM); + if (udp_listen_sock < 0) { + return (-1); + } + isc__nm_closesocket(udp_listen_sock); + udp_listen_sock = -1; + + tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + + tcp_listen_addr = (isc_sockaddr_t){ .length = 0 }; + tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM); + if (tcp_listen_sock < 0) { + return (-1); + } + isc__nm_closesocket(tcp_listen_sock); + tcp_listen_sock = -1; + + atomic_store(&do_send, true); + atomic_store(&nsends, esends); + + atomic_store(&saccepts, 0); + atomic_store(&sreads, 0); + atomic_store(&ssends, 0); + + atomic_store(&cconnects, 0); + atomic_store(&csends, 0); + atomic_store(&creads, 0); + atomic_store(&ctimeouts, 0); + allow_send_back = false; + stream_use_TLS = false; + + isc_refcount_init(&active_cconnects, 0); + isc_refcount_init(&active_csends, 0); + isc_refcount_init(&active_creads, 0); + isc_refcount_init(&active_ssends, 0); + isc_refcount_init(&active_sreads, 0); + + isc_nonce_buf(&send_magic, sizeof(send_magic)); + isc_nonce_buf(&stop_magic, sizeof(stop_magic)); + if (send_magic == stop_magic) { + return (-1); + } + + isc__netmgr_create(mctx, nworkers, &listen_nm); + assert_non_null(listen_nm); + isc_nm_settimeouts(listen_nm, T_INIT, T_IDLE, T_KEEPALIVE, + T_ADVERTISED); + + isc__netmgr_create(mctx, nworkers, &connect_nm); + assert_non_null(connect_nm); + isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE, + T_ADVERTISED); + + isc_quota_init(&listener_quota, 0); + atomic_store(&check_listener_quota, false); + + connect_readcb = connect_read_cb; + noanswer = false; + + if (isc_tlsctx_createserver(NULL, NULL, &tcp_listen_tlsctx) != + ISC_R_SUCCESS) + { + return (-1); + } + if (isc_tlsctx_createclient(&tcp_connect_tlsctx) != ISC_R_SUCCESS) { + return (-1); + } + + isc_tlsctx_enable_dot_client_alpn(tcp_connect_tlsctx); + + isc_tlsctx_client_session_cache_create( + mctx, tcp_connect_tlsctx, + ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, + &tcp_tlsctx_client_sess_cache); + + return (0); +} + +static int +teardown_test(void **state __attribute__((unused))) { + UNUSED(state); + + isc_tlsctx_free(&tcp_connect_tlsctx); + isc_tlsctx_free(&tcp_listen_tlsctx); + + isc__netmgr_destroy(&connect_nm); + assert_null(connect_nm); + + isc__netmgr_destroy(&listen_nm); + assert_null(listen_nm); + + WAIT_FOR_EQ(active_cconnects, 0); + WAIT_FOR_EQ(active_csends, 0); + WAIT_FOR_EQ(active_csends, 0); + WAIT_FOR_EQ(active_ssends, 0); + WAIT_FOR_EQ(active_sreads, 0); + + isc_refcount_destroy(&active_cconnects); + isc_refcount_destroy(&active_csends); + isc_refcount_destroy(&active_creads); + isc_refcount_destroy(&active_ssends); + isc_refcount_destroy(&active_sreads); + + isc_tlsctx_client_session_cache_detach(&tcp_tlsctx_client_sess_cache); + + return (0); +} + +/* Callbacks */ + +static void +noop_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *cbarg) { + UNUSED(handle); + UNUSED(eresult); + UNUSED(region); + UNUSED(cbarg); +} + +static unsigned int +noop_accept_cb(isc_nmhandle_t *handle, unsigned int result, void *cbarg) { + UNUSED(handle); + UNUSED(cbarg); + + if (result == ISC_R_SUCCESS) { + (void)atomic_fetch_add(&saccepts, 1); + } + + return (0); +} + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg); + +static void +connect_send(isc_nmhandle_t *handle); + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *sendhandle = handle; + + assert_non_null(sendhandle); + + UNUSED(cbarg); + + F(); + + if (eresult != ISC_R_SUCCESS) { + /* Send failed, we need to stop reading too */ + isc_nm_cancelread(handle); + goto unref; + } + + atomic_fetch_add(&csends, 1); +unref: + isc_refcount_decrement(&active_csends); + isc_nmhandle_detach(&sendhandle); +} + +static void +connect_send(isc_nmhandle_t *handle) { + isc_nmhandle_t *sendhandle = NULL; + isc_refcount_increment0(&active_csends); + isc_nmhandle_attach(handle, &sendhandle); + isc_nmhandle_setwritetimeout(handle, T_IDLE); + if (atomic_fetch_sub(&nsends, 1) > 1) { + isc_nm_send(sendhandle, &send_msg, connect_send_cb, NULL); + } else { + isc_nm_send(sendhandle, &stop_msg, connect_send_cb, NULL); + } +} + +static void +connect_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + UNUSED(cbarg); + + assert_non_null(handle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + assert_true(region->length >= sizeof(magic)); + + atomic_fetch_add(&creads, 1); + + memmove(&magic, region->base, sizeof(magic)); + + assert_true(magic == stop_magic || magic == send_magic); + + if (magic == send_magic && allow_send_back) { + connect_send(handle); + return; + } + +unref: + isc_refcount_decrement(&active_creads); + isc_nmhandle_detach(&handle); +} + +static void +connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + isc_refcount_decrement(&active_cconnects); + + if (eresult != ISC_R_SUCCESS || connect_readcb == NULL) { + return; + } + + atomic_fetch_add(&cconnects, 1); + + isc_refcount_increment0(&active_creads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, connect_readcb, NULL); + + connect_send(handle); +} + +static void +listen_send_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *sendhandle = handle; + + UNUSED(cbarg); + UNUSED(eresult); + + assert_non_null(sendhandle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + atomic_fetch_add(&ssends, 1); +unref: + isc_nmhandle_detach(&sendhandle); + isc_refcount_decrement(&active_ssends); +} + +static void +listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + uint64_t magic = 0; + + assert_non_null(handle); + + F(); + + if (eresult != ISC_R_SUCCESS) { + goto unref; + } + + atomic_fetch_add(&sreads, 1); + + assert_true(region->length >= sizeof(magic)); + + memmove(&magic, region->base, sizeof(magic)); + assert_true(magic == stop_magic || magic == send_magic); + + if (magic == send_magic) { + if (!noanswer) { + isc_nmhandle_t *sendhandle = NULL; + isc_nmhandle_attach(handle, &sendhandle); + isc_refcount_increment0(&active_ssends); + isc_nmhandle_setwritetimeout(sendhandle, T_IDLE); + isc_nm_send(sendhandle, &send_msg, listen_send_cb, + cbarg); + } + return; + } + +unref: + if (handle == cbarg) { + isc_refcount_decrement(&active_sreads); + isc_nmhandle_detach(&handle); + } +} + +static isc_result_t +listen_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + UNUSED(handle); + UNUSED(cbarg); + + F(); + + return (eresult); +} + +static isc_result_t +stream_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + if (eresult != ISC_R_SUCCESS) { + return (eresult); + } + + atomic_fetch_add(&saccepts, 1); + + isc_refcount_increment0(&active_sreads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, listen_read_cb, readhandle); + + return (ISC_R_SUCCESS); +} + +typedef void (*connect_func)(isc_nm_t *); + +static isc_threadresult_t +connect_thread(isc_threadarg_t arg) { + connect_func connect = (connect_func)arg; + isc_sockaddr_t connect_addr; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + while (atomic_load(&do_send)) { + uint_fast32_t active = + isc_refcount_increment0(&active_cconnects); + if (active > workers) { + /* + * If we have more active connections than workers, + * start slowing down the connections to prevent the + * thundering herd problem. + */ + isc_test_nap(active - workers); + } + connect(connect_nm); + } + + return ((isc_threadresult_t)0); +} + +/* UDP */ + +static void +udp_connect(isc_nm_t *nm) { + isc_nm_udpconnect(nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_open) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_open, UV_ENOMEM); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_bind) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_bind, UV_EADDRINUSE); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_listenudp_uv_udp_recv_start) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + WILL_RETURN(uv_udp_recv_start, UV_EADDRINUSE); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_not_equal(result, ISC_R_SUCCESS); + assert_null(listen_sock); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_open) { + WILL_RETURN(uv_udp_open, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_bind) { + WILL_RETURN(uv_udp_bind, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_udp_connect) { + WILL_RETURN(uv_udp_connect, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} +#endif + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_recv_buffer_size) { + WILL_RETURN(uv_recv_buffer_size, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(mock_udpconnect_uv_send_buffer_size) { + WILL_RETURN(uv_send_buffer_size, UV_ENOMEM); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + RESET_RETURN; +} + +ISC_RUN_TEST_IMPL(udp_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(udp_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(csends, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +timeout_retry_cb(isc_nmhandle_t *handle, isc_result_t eresult, + isc_region_t *region, void *cbarg) { + UNUSED(region); + UNUSED(cbarg); + + assert_non_null(handle); + + F(); + + if (eresult == ISC_R_TIMEDOUT && atomic_load(&csends) < 5) { + isc_nmhandle_settimeout(handle, T_SOFT); + connect_send(handle); + return; + } + + atomic_fetch_add(&ctimeouts, 1); + + isc_refcount_decrement(&active_creads); + isc_nmhandle_detach(&handle); +} + +ISC_RUN_TEST_IMPL(udp_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Listen using the noop callback so that client reads will time out. + */ + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, noop_recv_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Connect with client timeout set to 0.05 seconds, then sleep for at + * least a second for each 'tick'. timeout_retry_cb() will give up + * after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(udp_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(udp_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, &udp_connect_addr, &udp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(udp_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(udp_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(udp_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(udp_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listenudp(listen_nm, &udp_listen_addr, listen_read_cb, + NULL, 0, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, udp_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* Common stream protocols code */ + +static isc_quota_t * +tcp_listener_init_quota(size_t nthreads) { + isc_quota_t *quotap = NULL; + if (atomic_load(&check_listener_quota)) { + unsigned max_quota = ISC_MAX(nthreads / 2, 1); + isc_quota_max(&listener_quota, max_quota); + quotap = &listener_quota; + } + return (quotap); +} + +static void +tcp_connect(isc_nm_t *nm) { + isc_nm_tcpconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +#if HAVE_LIBNGHTTP2 +static void +tls_connect(isc_nm_t *nm); +#endif + +static stream_connect_function +get_stream_connect_function(void) { +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + return (tls_connect); + } +#endif + return (tcp_connect); +} + +static isc_result_t +stream_listen(isc_nm_accept_cb_t accept_cb, void *accept_cbarg, + size_t extrahandlesize, int backlog, isc_quota_t *quota, + isc_nmsocket_t **sockp) { + isc_result_t result = ISC_R_SUCCESS; + +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + result = isc_nm_listentls(listen_nm, &tcp_listen_addr, + accept_cb, accept_cbarg, + extrahandlesize, backlog, quota, + tcp_listen_tlsctx, sockp); + return (result); + } +#endif + result = isc_nm_listentcp(listen_nm, &tcp_listen_addr, accept_cb, + accept_cbarg, extrahandlesize, backlog, quota, + sockp); + + return (result); +} + +static void +stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout, + size_t extrahandlesize) { +#if HAVE_LIBNGHTTP2 + if (stream_use_TLS) { + isc_nm_tlsconnect(connect_nm, &tcp_connect_addr, + &tcp_listen_addr, cb, cbarg, + tcp_connect_tlsctx, + tcp_tlsctx_client_sess_cache, timeout, 0); + return; + } +#endif + isc_nm_tcpconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, cb, + cbarg, timeout, extrahandlesize); +} + +static void +stream_noop(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = stream_listen(noop_accept_cb, NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_noresponse(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = stream_listen(noop_accept_cb, NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_timeout_recovery(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = stream_listen(stream_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the client timeouts to 0.05 seconds. + */ + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + connect_readcb = timeout_retry_cb; + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +static void +stream_recv_one(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_quota_t *quotap = tcp_listener_init_quota(1); + + atomic_store(&nsends, 1); + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +static void +stream_recv_two(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_quota_t *quotap = tcp_listener_init_quota(1); + + atomic_store(&nsends, 2); + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + stream_connect(connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +static void +stream_recv_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends); + } + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +static void +stream_recv_half_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +stream_half_recv_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +stream_half_recv_half_send(void **state __attribute__((unused))) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + isc_quota_t *quotap = tcp_listener_init_quota(workers); + + SKIP_IN_CI; + + result = stream_listen(stream_accept_cb, NULL, 0, 0, quotap, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, get_stream_connect_function(), + &threads[i]); + } + + if (allow_send_back) { + WAIT_FOR_GE(cconnects, 1); + } else { + WAIT_FOR_GE(cconnects, esends / 2); + } + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* TCP */ +ISC_RUN_TEST_IMPL(tcp_noop) { stream_noop(state); } + +ISC_RUN_TEST_IMPL(tcp_noresponse) { stream_noresponse(state); } + +ISC_RUN_TEST_IMPL(tcp_timeout_recovery) { stream_timeout_recovery(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_one) { stream_recv_one(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_two) { stream_recv_two(state); } + +ISC_RUN_TEST_IMPL(tcp_recv_send) { + SKIP_IN_CI; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send) { + SKIP_IN_CI; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send) { + SKIP_IN_CI; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send) { + SKIP_IN_CI; + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_sendback) { + SKIP_IN_CI; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_sendback) { + SKIP_IN_CI; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_sendback) { + SKIP_IN_CI; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_sendback) { + SKIP_IN_CI; + stream_half_recv_half_send(state); +} + +/* TCP Quota */ + +ISC_RUN_TEST_IMPL(tcp_recv_one_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_two_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_quota) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_recv_half_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tcp_half_recv_half_send_quota_sendback) { + SKIP_IN_CI; + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_half_recv_half_send(state); +} + +/* TCPDNS */ + +static void +tcpdns_connect(isc_nm_t *nm) { + isc_nm_tcpdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + isc_refcount_increment0(&active_cconnects); + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + &listen_sock); + if (result != ISC_R_SUCCESS) { + isc_refcount_decrement(&active_cconnects); + isc_test_nap(1); + } + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + SKIP_IN_CI; + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the TCP client timeouts to 0.05 seconds, connect, + * then sleep for at least a second for each 'tick'. + * timeout_retry_cb() will give up after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); + + WAIT_FOR_EQ(cconnects, 2); + + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tcpdns_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentcpdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tcpdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +/* TLS */ + +#if HAVE_LIBNGHTTP2 +static void +tls_connect(isc_nm_t *nm) { + isc_nm_tlsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, tcp_connect_tlsctx, + tcp_tlsctx_client_sess_cache, T_CONNECT, 0); +} + +ISC_RUN_TEST_IMPL(tls_noop) { + stream_use_TLS = true; + stream_noop(state); +} + +ISC_RUN_TEST_IMPL(tls_noresponse) { + stream_use_TLS = true; + stream_noresponse(state); +} + +ISC_RUN_TEST_IMPL(tls_timeout_recovery) { + stream_use_TLS = true; + stream_timeout_recovery(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_one) { + stream_use_TLS = true; + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_two) { + stream_use_TLS = true; + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send) { + SKIP_IN_CI; + stream_use_TLS = true; + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + stream_half_recv_half_send(state); +} + +/* TLS quota */ + +ISC_RUN_TEST_IMPL(tls_recv_one_quota) { + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_one(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_two_quota) { + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_two(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_quota) { + SKIP_IN_CI; + stream_use_TLS = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_recv_half_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_recv_half_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_send(state); +} + +ISC_RUN_TEST_IMPL(tls_half_recv_half_send_quota_sendback) { + SKIP_IN_CI; + stream_use_TLS = true; + allow_send_back = true; + atomic_store(&check_listener_quota, true); + stream_half_recv_half_send(state); +} +#endif + +/* TLSDNS */ + +static void +tlsdns_connect(isc_nm_t *nm) { + isc_nm_tlsdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); +} + +ISC_RUN_TEST_IMPL(tlsdns_noop) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + connect_readcb = NULL; + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + isc__netmgr_shutdown(connect_nm); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_noresponse) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_EQ(saccepts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_timeout_recovery) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + + SKIP_IN_CI; + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + /* + * Accept connections but don't send responses, forcing client + * reads to time out. + */ + noanswer = true; + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Shorten all the TCP client timeouts to 0.05 seconds, connect, + * then sleep for at least a second for each 'tick'. + * timeout_retry_cb() will give up after five timeouts. + */ + connect_readcb = timeout_retry_cb; + isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT); + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_SOFT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_GE(csends, 1); + WAIT_FOR_GE(csends, 2); + WAIT_FOR_GE(csends, 3); + WAIT_FOR_GE(csends, 4); + WAIT_FOR_EQ(csends, 5); + WAIT_FOR_EQ(ctimeouts, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_one) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 1); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 1); + WAIT_FOR_EQ(sreads, 1); + WAIT_FOR_EQ(ssends, 0); + WAIT_FOR_EQ(creads, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(csends, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 1); + atomic_assert_int_eq(ssends, 0); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_two) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + + atomic_store(&nsends, 2); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 1); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(cconnects, 2); + + WAIT_FOR_LE(nsends, 0); + WAIT_FOR_EQ(csends, 2); + WAIT_FOR_EQ(sreads, 2); + WAIT_FOR_EQ(ssends, 1); + WAIT_FOR_EQ(creads, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 2); + atomic_assert_int_eq(csends, 2); + atomic_assert_int_eq(creads, 1); + atomic_assert_int_eq(sreads, 2); + atomic_assert_int_eq(ssends, 1); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends); + WAIT_FOR_GE(csends, esends); + WAIT_FOR_GE(sreads, esends); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_FULL(csends); + CHECK_RANGE_FULL(creads); + CHECK_RANGE_FULL(sreads); + CHECK_RANGE_FULL(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_half_recv_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + /* Try to send a little while longer */ + isc_test_nap((esends / 2) * 10); + + isc__netmgr_shutdown(connect_nm); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +ISC_RUN_TEST_IMPL(tlsdns_half_recv_half_send) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_thread_t threads[workers]; + + SKIP_IN_CI; + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, + listen_read_cb, NULL, listen_accept_cb, + NULL, 0, 0, NULL, tcp_listen_tlsctx, + &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + memset(threads, 0, sizeof(threads)); + for (size_t i = 0; i < workers; i++) { + isc_thread_create(connect_thread, tlsdns_connect, &threads[i]); + } + + WAIT_FOR_GE(cconnects, esends / 2); + WAIT_FOR_GE(csends, esends / 2); + WAIT_FOR_GE(sreads, esends / 2); + WAIT_FOR_GE(ssends, esends / 2); + WAIT_FOR_GE(creads, esends / 2); + + isc__netmgr_shutdown(connect_nm); + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + + DONE(); + for (size_t i = 0; i < workers; i++) { + isc_thread_join(threads[i], NULL); + } + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + CHECK_RANGE_HALF(csends); + CHECK_RANGE_HALF(creads); + CHECK_RANGE_HALF(sreads); + CHECK_RANGE_HALF(ssends); +} + +static void +tlsdns_connect_connect_noalpn(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + isc_nmhandle_t *readhandle = NULL; + + UNUSED(cbarg); + + F(); + + isc_refcount_decrement(&active_cconnects); + + if (eresult != ISC_R_SUCCESS || connect_readcb == NULL || + isc_nm_xfr_checkperm(handle) != ISC_R_SUCCESS) + { + return; + } + + atomic_fetch_add(&cconnects, 1); + + isc_refcount_increment0(&active_creads); + isc_nmhandle_attach(handle, &readhandle); + isc_nm_read(handle, connect_readcb, NULL); + + connect_send(handle); +} + +ISC_RUN_TEST_IMPL(tlsdns_connect_noalpn) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + isc_tlsctx_t *connect_tlsctx_noalpn = NULL; + + result = isc_tlsctx_createclient(&connect_tlsctx_noalpn); + assert_true(result == ISC_R_SUCCESS); + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + result = isc_nm_listentlsdns(listen_nm, &tcp_listen_addr, noop_recv_cb, + NULL, noop_accept_cb, NULL, 0, 0, NULL, + tcp_listen_tlsctx, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + tlsdns_connect_connect_noalpn, NULL, T_CONNECT, 0, + connect_tlsctx_noalpn, NULL); + + WAIT_FOR_EQ(active_cconnects, 0); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(cconnects, 0); + atomic_assert_int_eq(csends, 0); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); + + isc_tlsctx_free(&connect_tlsctx_noalpn); +} + +#ifdef HAVE_LIBNGHTTP2 + +static isc_result_t +tls_accept_cb_noalpn(isc_nmhandle_t *handle, isc_result_t eresult, + void *cbarg) { + F(); + + if (eresult != ISC_R_SUCCESS) { + return (eresult); + } + + atomic_fetch_add(&saccepts, 1); + + if (isc_nm_xfr_checkperm(handle) != ISC_R_SUCCESS) { + return (ISC_R_FAILURE); + } + + return (stream_accept_cb(handle, eresult, cbarg)); +} + +ISC_RUN_TEST_IMPL(tlsdns_listen_noalpn) { + isc_result_t result = ISC_R_SUCCESS; + isc_nmsocket_t *listen_sock = NULL; + isc_sockaddr_t connect_addr; + isc_tlsctx_t *server_tlsctx_noalpn = NULL; + + result = isc_tlsctx_createserver(NULL, NULL, &server_tlsctx_noalpn); + assert_true(result == ISC_R_SUCCESS); + + connect_addr = (isc_sockaddr_t){ .length = 0 }; + isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); + + /* We use TLS stream listener here intentionally, as it does not + * try to do ALPN. */ + result = isc_nm_listentls(listen_nm, &tcp_listen_addr, + tls_accept_cb_noalpn, NULL, 0, 0, NULL, + server_tlsctx_noalpn, &listen_sock); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache); + + WAIT_FOR_EQ(saccepts, 1); + WAIT_FOR_EQ(cconnects, 1); + + isc_nm_stoplistening(listen_sock); + isc_nmsocket_close(&listen_sock); + assert_null(listen_sock); + isc__netmgr_shutdown(connect_nm); + + X(cconnects); + X(csends); + X(creads); + X(sreads); + X(ssends); + + atomic_assert_int_eq(saccepts, 1); + atomic_assert_int_eq(cconnects, 1); + atomic_assert_int_eq(creads, 0); + atomic_assert_int_eq(sreads, 0); + atomic_assert_int_eq(ssends, 0); + + isc_tlsctx_free(&server_tlsctx_noalpn); +} +#endif /* HAVE_LIBNGHTTP2 */ + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_open, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_bind, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_listenudp_uv_udp_recv_start, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_open, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_bind, setup_test, teardown_test) +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_udp_connect, setup_test, teardown_test) +#endif +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_recv_buffer_size, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(mock_udpconnect_uv_send_buffer_size, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(udp_half_recv_half_send, setup_test, teardown_test) + +/* TCP */ +ISC_TEST_ENTRY_CUSTOM(tcp_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_sendback, setup_test, + teardown_test) + +/* TCP Quota */ +ISC_TEST_ENTRY_CUSTOM(tcp_recv_one_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_two_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_send_quota_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_recv_half_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcp_half_recv_half_send_quota_sendback, setup_test, + teardown_test) + +/* TCPDNS */ +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tcpdns_half_recv_half_send, setup_test, teardown_test) + +#if HAVE_LIBNGHTTP2 +/* TLS */ +ISC_TEST_ENTRY_CUSTOM(tls_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_sendback, setup_test, + teardown_test) + +/* TLS quota */ +ISC_TEST_ENTRY_CUSTOM(tls_recv_one_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_two_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_quota, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_send_quota_sendback, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_recv_half_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_send_quota_sendback, setup_test, + teardown_test) +ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_quota_sendback, setup_test, + teardown_test) +#endif + +/* TLSDNS */ +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_one, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_two, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_noop, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_noresponse, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_timeout_recovery, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_half_recv_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_half_recv_half_send, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(tlsdns_connect_noalpn, setup_test, teardown_test) +#ifdef HAVE_LIBNGHTTP2 +ISC_TEST_ENTRY_CUSTOM(tlsdns_listen_noalpn, setup_test, teardown_test) +#endif + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/parse_test.c b/tests/isc/parse_test.c new file mode 100644 index 0000000..a5b516a --- /dev/null +++ b/tests/isc/parse_test.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/parseint.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* Test for 32 bit overflow on 64 bit machines in isc_parse_uint32 */ +ISC_RUN_TEST_IMPL(parse_overflow) { + isc_result_t result; + uint32_t output; + + result = isc_parse_uint32(&output, "1234567890", 10); + assert_int_equal(ISC_R_SUCCESS, result); + assert_int_equal(1234567890, output); + + result = isc_parse_uint32(&output, "123456789012345", 10); + assert_int_equal(ISC_R_RANGE, result); + + result = isc_parse_uint32(&output, "12345678901234567890", 10); + assert_int_equal(ISC_R_RANGE, result); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(parse_overflow) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/pool_test.c b/tests/isc/pool_test.c new file mode 100644 index 0000000..35d556f --- /dev/null +++ b/tests/isc/pool_test.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/mem.h> +#include <isc/pool.h> +#include <isc/util.h> + +#include <tests/isc.h> + +static isc_result_t +poolinit(void **target, void *arg) { + isc_result_t result; + + isc_taskmgr_t *mgr = (isc_taskmgr_t *)arg; + isc_task_t *task = NULL; + result = isc_task_create(mgr, 0, &task); + if (result != ISC_R_SUCCESS) { + return (result); + } + + *target = (void *)task; + return (ISC_R_SUCCESS); +} + +static void +poolfree(void **target) { + isc_task_t *task = *(isc_task_t **)target; + isc_task_destroy(&task); + *target = NULL; +} + +/* Create a pool */ +ISC_RUN_TEST_IMPL(create_pool) { + isc_result_t result; + isc_pool_t *pool = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 8, poolfree, poolinit, taskmgr, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool), 8); + + isc_pool_destroy(&pool); + assert_null(pool); +} + +/* Resize a pool */ +ISC_RUN_TEST_IMPL(expand_pool) { + isc_result_t result; + isc_pool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 10, poolfree, poolinit, taskmgr, &pool1); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool1), 10); + + /* resizing to a smaller size should have no effect */ + hold = pool1; + result = isc_pool_expand(&pool1, 5, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to the same size should have no effect */ + hold = pool1; + result = isc_pool_expand(&pool1, 10, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to larger size should make a new pool */ + hold = pool1; + result = isc_pool_expand(&pool1, 20, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool2), 20); + assert_ptr_not_equal(pool2, hold); + assert_null(pool1); + + isc_pool_destroy(&pool2); + assert_null(pool2); +} + +/* Get objects */ +ISC_RUN_TEST_IMPL(get_objects) { + isc_result_t result; + isc_pool_t *pool = NULL; + void *item; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_pool_create(mctx, 2, poolfree, poolinit, taskmgr, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_pool_count(pool), 2); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task1); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task2); + + item = isc_pool_get(pool); + assert_non_null(item); + isc_task_attach((isc_task_t *)item, &task3); + + isc_task_detach(&task1); + isc_task_detach(&task2); + isc_task_detach(&task3); + + isc_pool_destroy(&pool); + assert_null(pool); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(create_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(expand_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(get_objects, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/quota_test.c b/tests/isc/quota_test.c new file mode 100644 index 0000000..9b202b9 --- /dev/null +++ b/tests/isc/quota_test.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/quota.h> +#include <isc/result.h> +#include <isc/thread.h> +#include <isc/util.h> + +#include "netmgr/uv-compat.h" + +#include <tests/isc.h> + +ISC_RUN_TEST_IMPL(isc_quota_get_set) { + UNUSED(state); + isc_quota_t quota; + isc_quota_t *quota2 = NULL; + isc_quota_init("a, 100); + + assert_int_equal(isc_quota_getmax("a), 100); + assert_int_equal(isc_quota_getsoft("a), 0); + + isc_quota_max("a, 50); + isc_quota_soft("a, 30); + + assert_int_equal(isc_quota_getmax("a), 50); + assert_int_equal(isc_quota_getsoft("a), 30); + + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_attach("a, "a2); + assert_int_equal(isc_quota_getused("a), 1); + isc_quota_detach("a2); + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +static void +add_quota(isc_quota_t *source, isc_quota_t **target, + isc_result_t expected_result, int expected_used) { + isc_result_t result; + + *target = NULL; + + result = isc_quota_attach(source, target); + assert_int_equal(result, expected_result); + + switch (expected_result) { + case ISC_R_SUCCESS: + case ISC_R_SOFTQUOTA: + assert_ptr_equal(*target, source); + break; + default: + assert_null(*target); + break; + } + + assert_int_equal(isc_quota_getused(source), expected_used); +} + +ISC_RUN_TEST_IMPL(isc_quota_hard) { + isc_quota_t quota; + isc_quota_t *quotas[110]; + int i; + UNUSED(state); + + isc_quota_init("a, 100); + + for (i = 0; i < 100; i++) { + add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + } + + add_quota("a, "as[100], ISC_R_QUOTA, 100); + + assert_int_equal(isc_quota_getused("a), 100); + + isc_quota_detach("as[0]); + assert_null(quotas[0]); + + add_quota("a, "as[100], ISC_R_SUCCESS, 100); + add_quota("a, "as[101], ISC_R_QUOTA, 100); + + for (i = 100; i > 0; i--) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), i - 1); + } + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +ISC_RUN_TEST_IMPL(isc_quota_soft) { + isc_quota_t quota; + isc_quota_t *quotas[110]; + int i; + UNUSED(state); + + isc_quota_init("a, 100); + isc_quota_soft("a, 50); + + for (i = 0; i < 50; i++) { + add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + } + for (i = 50; i < 100; i++) { + add_quota("a, "as[i], ISC_R_SOFTQUOTA, i + 1); + } + + add_quota("a, "as[i], ISC_R_QUOTA, 100); + + for (i = 99; i >= 0; i--) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), i); + } + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +static atomic_uint_fast32_t cb_calls = 0; +static isc_quota_cb_t cbs[30]; +static isc_quota_t *qp; + +static void +callback(isc_quota_t *quota, void *data) { + int val = *(int *)data; + /* Callback is not called if we get the quota directly */ + assert_int_not_equal(val, -1); + + /* We get the proper quota pointer */ + assert_ptr_equal(quota, qp); + + /* Verify that the callbacks are called in order */ + int v = atomic_fetch_add_relaxed(&cb_calls, 1); + assert_int_equal(v, val); + + /* + * First 5 will be detached by the test function, + * for the last 5 - do a 'chain detach'. + */ + if (v >= 5) { + isc_quota_detach("a); + } +} + +ISC_RUN_TEST_IMPL(isc_quota_callback) { + isc_result_t result; + isc_quota_t quota; + isc_quota_t *quotas[30]; + qp = "a; + /* + * - 10 calls that end with SUCCESS + * - 10 calls that end with SOFTQUOTA + * - 10 callbacks + */ + int ints[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int i; + UNUSED(state); + + isc_quota_init("a, 20); + isc_quota_soft("a, 10); + + for (i = 0; i < 10; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(quotas[i], "a); + assert_int_equal(isc_quota_getused("a), i + 1); + } + for (i = 10; i < 20; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_SOFTQUOTA); + assert_ptr_equal(quotas[i], "a); + assert_int_equal(isc_quota_getused("a), i + 1); + } + + for (i = 20; i < 30; i++) { + quotas[i] = NULL; + isc_quota_cb_init(&cbs[i], callback, &ints[i]); + result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + assert_int_equal(result, ISC_R_QUOTA); + assert_ptr_equal(quotas[i], NULL); + assert_int_equal(isc_quota_getused("a), 20); + } + assert_int_equal(atomic_load(&cb_calls), 0); + + for (i = 0; i < 5; i++) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), 20); + assert_int_equal(atomic_load(&cb_calls), i + 1); + } + /* That should cause a chain reaction */ + isc_quota_detach("as[5]); + assert_int_equal(atomic_load(&cb_calls), 10); + + /* Release the quotas that we did not released in the callback */ + for (i = 0; i < 5; i++) { + qp = "a; + isc_quota_detach(&qp); + } + + for (i = 6; i < 20; i++) { + isc_quota_detach("as[i]); + assert_null(quotas[i]); + assert_int_equal(isc_quota_getused("a), 19 - i); + } + assert_int_equal(atomic_load(&cb_calls), 10); + + assert_int_equal(isc_quota_getused("a), 0); + isc_quota_destroy("a); +} + +/* + * Multithreaded quota callback test: + * - quota set to 100 + * - 10 threads, each trying to get 100 quotas. + * - creates a separate thread to release it after 10ms + */ + +typedef struct qthreadinfo { + atomic_uint_fast32_t direct; + atomic_uint_fast32_t callback; + isc_quota_t *quota; + isc_quota_cb_t callbacks[100]; +} qthreadinfo_t; + +static atomic_uint_fast32_t g_tnum = 0; +/* at most 10 * 100 quota_detach threads */ +isc_thread_t g_threads[10 * 100]; + +static void * +quota_detach(void *quotap) { + isc_quota_t *quota = (isc_quota_t *)quotap; + uv_sleep(10); + isc_quota_detach("a); + return ((isc_threadresult_t)0); +} + +static void +quota_callback(isc_quota_t *quota, void *data) { + qthreadinfo_t *qti = (qthreadinfo_t *)data; + atomic_fetch_add_relaxed(&qti->callback, 1); + int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); + isc_thread_create(quota_detach, quota, &g_threads[tnum]); +} + +static isc_threadresult_t +quota_thread(void *qtip) { + qthreadinfo_t *qti = (qthreadinfo_t *)qtip; + for (int i = 0; i < 100; i++) { + isc_quota_cb_init(&qti->callbacks[i], quota_callback, qti); + isc_quota_t *quota = NULL; + isc_result_t result = isc_quota_attach_cb(qti->quota, "a, + &qti->callbacks[i]); + if (result == ISC_R_SUCCESS) { + atomic_fetch_add_relaxed(&qti->direct, 1); + int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); + isc_thread_create(quota_detach, quota, + &g_threads[tnum]); + } + } + return ((isc_threadresult_t)0); +} + +ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { + UNUSED(state); + isc_quota_t quota; + int i; + + isc_quota_init("a, 100); + static qthreadinfo_t qtis[10]; + isc_thread_t threads[10]; + for (i = 0; i < 10; i++) { + atomic_init(&qtis[i].direct, 0); + atomic_init(&qtis[i].callback, 0); + qtis[i].quota = "a; + isc_thread_create(quota_thread, &qtis[i], &threads[i]); + } + for (i = 0; i < 10; i++) { + isc_thread_join(threads[i], NULL); + } + + for (i = 0; i < (int)atomic_load(&g_tnum); i++) { + isc_thread_join(g_threads[i], NULL); + } + int direct = 0, ncallback = 0; + + for (i = 0; i < 10; i++) { + direct += atomic_load(&qtis[i].direct); + ncallback += atomic_load(&qtis[i].callback); + } + /* Total quota gained must be 10 threads * 100 tries */ + assert_int_equal(direct + ncallback, 10 * 100); + /* + * At least 100 must be direct, the rest is virtually random: + * - in a regular run I'm constantly getting 100:900 ratio + * - under rr - usually around ~120:880 + * - under rr -h - 1000:0 + */ + assert_true(direct >= 100); + + isc_quota_destroy("a); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_quota_get_set) +ISC_TEST_ENTRY(isc_quota_hard) +ISC_TEST_ENTRY(isc_quota_soft) +ISC_TEST_ENTRY(isc_quota_callback) +ISC_TEST_ENTRY(isc_quota_callback_mt) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/radix_test.c b/tests/isc/radix_test.c new file mode 100644 index 0000000..fe589fe --- /dev/null +++ b/tests/isc/radix_test.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/mem.h> +#include <isc/netaddr.h> +#include <isc/radix.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test radix node removal */ +ISC_RUN_TEST_IMPL(isc_radix_remove) { + isc_radix_tree_t *radix = NULL; + isc_radix_node_t *node; + isc_prefix_t prefix; + isc_result_t result; + struct in_addr in_addr; + isc_netaddr_t netaddr; + + UNUSED(state); + + result = isc_radix_create(mctx, &radix, 32); + assert_int_equal(result, ISC_R_SUCCESS); + + in_addr.s_addr = inet_addr("1.1.1.1"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 32); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)32; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("1.0.0.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 8); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)8; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("1.1.1.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 24); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)24; + isc_refcount_destroy(&prefix.refcount); + + isc_radix_remove(radix, node); + + isc_radix_destroy(radix, NULL); +} + +/* test radix searching */ +ISC_RUN_TEST_IMPL(isc_radix_search) { + isc_radix_tree_t *radix = NULL; + isc_radix_node_t *node; + isc_prefix_t prefix; + isc_result_t result; + struct in_addr in_addr; + isc_netaddr_t netaddr; + + UNUSED(state); + + result = isc_radix_create(mctx, &radix, 32); + assert_int_equal(result, ISC_R_SUCCESS); + + in_addr.s_addr = inet_addr("3.3.3.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 24); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)1; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("3.3.0.0"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 16); + + node = NULL; + result = isc_radix_insert(radix, &node, NULL, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + node->data[0] = (void *)2; + isc_refcount_destroy(&prefix.refcount); + + in_addr.s_addr = inet_addr("3.3.3.3"); + isc_netaddr_fromin(&netaddr, &in_addr); + NETADDR_TO_PREFIX_T(&netaddr, prefix, 22); + + node = NULL; + result = isc_radix_search(radix, &node, &prefix); + assert_int_equal(result, ISC_R_SUCCESS); + assert_ptr_equal(node->data[0], (void *)2); + + isc_refcount_destroy(&prefix.refcount); + + isc_radix_destroy(radix, NULL); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_radix_remove) +ISC_TEST_ENTRY(isc_radix_search) + +ISC_TEST_LIST_END +ISC_TEST_MAIN diff --git a/tests/isc/random_test.c b/tests/isc/random_test.c new file mode 100644 index 0000000..1935846 --- /dev/null +++ b/tests/isc/random_test.c @@ -0,0 +1,787 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * IMPORTANT NOTE: + * These tests work by generating a large number of pseudo-random numbers + * and then statistically analyzing them to determine whether they seem + * random. The test is expected to fail on occasion by random happenstance. + */ + +#include <inttypes.h> +#include <math.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/commandline.h> +#include <isc/mem.h> +#include <isc/nonce.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +#define REPS 25000 + +typedef double(pvalue_func_t)(uint16_t *values, size_t length); + +/* igamc(), igam(), etc. were adapted (and cleaned up) from the Cephes + * math library: + * + * Cephes Math Library Release 2.8: June, 2000 + * Copyright 1985, 1987, 2000 by Stephen L. Moshier + * + * The Cephes math library was released into the public domain as part + * of netlib. + */ + +static double MACHEP = 1.11022302462515654042E-16; +static double MAXLOG = 7.09782712893383996843E2; +static double big = 4.503599627370496e15; +static double biginv = 2.22044604925031308085e-16; + +static double +igamc(double a, double x); +static double +igam(double a, double x); + +typedef enum { + ISC_RANDOM8, + ISC_RANDOM16, + ISC_RANDOM32, + ISC_RANDOM_BYTES, + ISC_RANDOM_UNIFORM, + ISC_NONCE_BYTES +} isc_random_func; + +static double +igamc(double a, double x) { + double ans, ax, c, r, t, y, z; + double pkm1, pkm2, qkm1, qkm2; + + if ((x <= 0) || (a <= 0)) { + return (1.0); + } + + if ((x < 1.0) || (x < a)) { + return (1.0 - igam(a, x)); + } + + ax = a * log(x) - x - lgamma(a); + if (ax < -MAXLOG) { + print_error("# igamc: UNDERFLOW, ax=%f\n", ax); + return (0.0); + } + ax = exp(ax); + + /* continued fraction */ + y = 1.0 - a; + z = x + y + 1.0; + c = 0.0; + pkm2 = 1.0; + qkm2 = x; + pkm1 = x + 1.0; + qkm1 = z * x; + ans = pkm1 / qkm1; + + do { + double yc, pk, qk; + c += 1.0; + y += 1.0; + z += 2.0; + yc = y * c; + pk = pkm1 * z - pkm2 * yc; + qk = qkm1 * z - qkm2 * yc; + if (qk != 0) { + r = pk / qk; + t = fabs((ans - r) / r); + ans = r; + } else { + t = 1.0; + } + + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + + if (fabs(pk) > big) { + pkm2 *= biginv; + pkm1 *= biginv; + qkm2 *= biginv; + qkm1 *= biginv; + } + } while (t > MACHEP); + + return (ans * ax); +} + +static double +igam(double a, double x) { + double ans, ax, c, r; + + if ((x <= 0) || (a <= 0)) { + return (0.0); + } + + if ((x > 1.0) && (x > a)) { + return (1.0 - igamc(a, x)); + } + + /* Compute x**a * exp(-x) / md_gamma(a) */ + ax = a * log(x) - x - lgamma(a); + if (ax < -MAXLOG) { + print_error("# igam: UNDERFLOW, ax=%f\n", ax); + return (0.0); + } + ax = exp(ax); + + /* power series */ + r = a; + c = 1.0; + ans = 1.0; + + do { + r += 1.0; + c *= x / r; + ans += c; + } while (c / ans > MACHEP); + + return (ans * ax / a); +} + +static int8_t scounts_table[65536]; +static uint8_t bitcounts_table[65536]; + +static int8_t +scount_calculate(uint16_t n) { + int i; + int8_t sc; + + sc = 0; + for (i = 0; i < 16; i++) { + uint16_t lsb; + + lsb = n & 1; + if (lsb != 0) { + sc += 1; + } else { + sc -= 1; + } + + n >>= 1; + } + + return (sc); +} + +static uint8_t +bitcount_calculate(uint16_t n) { + int i; + uint8_t bc; + + bc = 0; + for (i = 0; i < 16; i++) { + uint16_t lsb; + + lsb = n & 1; + if (lsb != 0) { + bc += 1; + } + + n >>= 1; + } + + return (bc); +} + +static void +tables_init(void) { + uint32_t i; + + for (i = 0; i < 65536; i++) { + scounts_table[i] = scount_calculate(i); + bitcounts_table[i] = bitcount_calculate(i); + } +} + +/* + * The following code for computing Marsaglia's rank is based on the + * implementation in cdbinrnk.c from the diehard tests by George + * Marsaglia. + * + * This function destroys (modifies) the data passed in bits. + */ +static uint32_t +matrix_binaryrank(uint32_t *bits, size_t rows, size_t cols) { + unsigned int rt = 0; + uint32_t rank = 0; + uint32_t tmp; + + for (size_t k = 0; k < rows; k++) { + size_t i = k; + + while (rt >= cols || ((bits[i] >> rt) & 1) == 0) { + i++; + + if (i < rows) { + continue; + } else { + rt++; + if (rt < cols) { + i = k; + continue; + } + } + + return (rank); + } + + rank++; + if (i != k) { + tmp = bits[i]; + bits[i] = bits[k]; + bits[k] = tmp; + } + + for (size_t j = i + 1; j < rows; j++) { + if (((bits[j] >> rt) & 1) == 0) { + continue; + } else { + bits[j] ^= bits[k]; + } + } + + rt++; + } + + return (rank); +} + +static void +random_test(pvalue_func_t *func, isc_random_func test_func) { + uint32_t m; + uint32_t j; + uint32_t histogram[11] = { 0 }; + uint32_t passed; + double proportion; + double p_hat; + double lower_confidence, higher_confidence; + double chi_square; + double p_value_t; + double alpha; + + tables_init(); + + m = 1000; + passed = 0; + + for (j = 0; j < m; j++) { + uint32_t i; + uint32_t values[REPS]; + uint16_t *uniform_values; + double p_value; + + switch (test_func) { + case ISC_RANDOM8: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random8(); + } + break; + case ISC_RANDOM16: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random16(); + } + break; + case ISC_RANDOM32: + for (i = 0; i < (sizeof(values) / sizeof(*values)); i++) + { + values[i] = isc_random32(); + } + break; + case ISC_RANDOM_BYTES: + isc_random_buf(values, sizeof(values)); + break; + case ISC_RANDOM_UNIFORM: + uniform_values = (uint16_t *)values; + for (i = 0; + i < (sizeof(values) / (sizeof(*uniform_values))); + i++) + { + uniform_values[i] = + isc_random_uniform(UINT16_MAX); + } + break; + case ISC_NONCE_BYTES: + isc_nonce_buf(values, sizeof(values)); + break; + } + + p_value = (*func)((uint16_t *)values, REPS * 2); + if (p_value >= 0.01) { + passed++; + } + + assert_in_range(p_value, 0.0, 1.0); + + i = (int)floor(p_value * 10); + histogram[i]++; + } + + /* + * Check proportion of sequences passing a test (see section + * 4.2.1 in NIST SP 800-22). + */ + alpha = 0.01; /* the significance level */ + proportion = (double)passed / (double)m; + p_hat = 1.0 - alpha; + lower_confidence = p_hat - (3.0 * sqrt((p_hat * (1.0 - p_hat)) / m)); + higher_confidence = p_hat + (3.0 * sqrt((p_hat * (1.0 - p_hat)) / m)); + + assert_in_range(proportion, lower_confidence, higher_confidence); + + /* + * Check uniform distribution of p-values (see section 4.2.2 in + * NIST SP 800-22). + */ + + /* Fold histogram[10] (p_value = 1.0) into histogram[9] for + * interval [0.9, 1.0] + */ + histogram[9] += histogram[10]; + histogram[10] = 0; + + /* Pre-requisite that at least 55 sequences are processed. */ + assert_true(m >= 55); + + chi_square = 0.0; + for (j = 0; j < 10; j++) { + double numer; + double denom; + + numer = (histogram[j] - (m / 10.0)) * + (histogram[j] - (m / 10.0)); + denom = m / 10.0; + chi_square += numer / denom; + } + + p_value_t = igamc(9 / 2.0, chi_square / 2.0); + + assert_true(p_value_t >= 0.0001); +} + +/* + * This is a frequency (monobits) test taken from the NIST SP 800-22 + * RANDOM test suite. + */ +static double +monobit(uint16_t *values, size_t length) { + size_t i; + int32_t scount; + uint32_t numbits; + double s_obs; + double p_value; + + UNUSED(mctx); + + numbits = length * sizeof(*values) * 8; + scount = 0; + + for (i = 0; i < length; i++) { + scount += scounts_table[values[i]]; + } + + /* Preconditions (section 2.1.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + + s_obs = abs(scount) / sqrt(numbits); + p_value = erfc(s_obs / sqrt(2.0)); + + return (p_value); +} + +/* + * This is the runs test taken from the NIST SP 800-22 RNG test suite. + */ +static double +runs(uint16_t *values, size_t length) { + size_t i; + uint32_t bcount; + uint32_t numbits; + double pi; + double tau; + uint32_t j; + uint32_t b; + uint8_t bit_prev; + uint32_t v_obs; + double numer; + double denom; + double p_value; + + UNUSED(mctx); + + numbits = length * sizeof(*values) * 8; + bcount = 0; + + for (i = 0; i < length; i++) { + bcount += bitcounts_table[values[i]]; + } + + pi = (double)bcount / (double)numbits; + tau = 2.0 / sqrt(numbits); + + /* Preconditions (section 2.3.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + + /* + * Pre-condition implied from the monobit test. This can fail + * for some sequences, and the p-value is taken as 0 in these + * cases. + */ + if (fabs(pi - 0.5) >= tau) { + return (0.0); + } + + /* Compute v_obs */ + j = 0; + b = 14; + bit_prev = (values[j] & (1U << 15)) == 0 ? 0 : 1; + + v_obs = 0; + + for (i = 1; i < numbits; i++) { + uint8_t bit_this = (values[j] & (1U << b)) == 0 ? 0 : 1; + if (b == 0) { + b = 15; + j++; + } else { + b--; + } + + v_obs += bit_this ^ bit_prev; + + bit_prev = bit_this; + } + + v_obs += 1; + + numer = fabs(v_obs - (2.0 * numbits * pi * (1.0 - pi))); + denom = 2.0 * sqrt(2.0 * numbits) * pi * (1.0 - pi); + + p_value = erfc(numer / denom); + + return (p_value); +} + +/* + * This is the block frequency test taken from the NIST SP 800-22 RNG + * test suite. + */ +static double +blockfrequency(uint16_t *values, size_t length) { + uint32_t i; + uint32_t numbits; + uint32_t mbits; + uint32_t mwords; + uint32_t numblocks; + double *pi; + double chi_square; + double p_value; + + numbits = length * sizeof(*values) * 8; + mbits = 32000; + mwords = mbits / 16; + numblocks = numbits / mbits; + + /* Preconditions (section 2.2.7 in NIST SP 800-22) */ + assert_true(numbits >= 100); + assert_true(mbits >= 20); + assert_true((double)mbits > (0.01 * numbits)); + assert_true(numblocks < 100); + assert_true(numbits >= (mbits * numblocks)); + + pi = isc_mem_get(mctx, numblocks * sizeof(double)); + assert_non_null(pi); + + for (i = 0; i < numblocks; i++) { + uint32_t j; + pi[i] = 0.0; + for (j = 0; j < mwords; j++) { + uint32_t idx; + + idx = i * mwords + j; + pi[i] += bitcounts_table[values[idx]]; + } + pi[i] /= mbits; + } + + /* Compute chi_square */ + chi_square = 0.0; + for (i = 0; i < numblocks; i++) { + chi_square += (pi[i] - 0.5) * (pi[i] - 0.5); + } + + chi_square *= 4 * mbits; + + isc_mem_put(mctx, pi, numblocks * sizeof(double)); + + p_value = igamc(numblocks * 0.5, chi_square * 0.5); + + return (p_value); +} + +/* + * This is the binary matrix rank test taken from the NIST SP 800-22 RNG + * test suite. + */ +static double +binarymatrixrank(uint16_t *values, size_t length) { + uint32_t i; + size_t matrix_m; + size_t matrix_q; + uint32_t num_matrices; + size_t numbits; + uint32_t fm_0; + uint32_t fm_1; + uint32_t fm_rest; + double term1; + double term2; + double term3; + double chi_square; + double p_value; + + UNUSED(mctx); + + matrix_m = 32; + matrix_q = 32; + num_matrices = length / ((matrix_m * matrix_q) / 16); + numbits = num_matrices * matrix_m * matrix_q; + + /* Preconditions (section 2.5.7 in NIST SP 800-22) */ + assert_int_equal(matrix_m, 32); + assert_int_equal(matrix_q, 32); + assert_true(numbits >= (38 * matrix_m * matrix_q)); + + fm_0 = 0; + fm_1 = 0; + fm_rest = 0; + for (i = 0; i < num_matrices; i++) { + /* + * Each uint32_t supplies 32 bits, so a 32x32 bit matrix + * takes up uint32_t array of size 32. + */ + uint32_t bits[32]; + int j; + uint32_t rank; + + for (j = 0; j < 32; j++) { + size_t idx; + uint32_t r1; + uint32_t r2; + + idx = i * ((matrix_m * matrix_q) / 16); + idx += j * 2; + + r1 = values[idx]; + r2 = values[idx + 1]; + bits[j] = (r1 << 16) | r2; + } + + rank = matrix_binaryrank(bits, matrix_m, matrix_q); + + if (rank == matrix_m) { + fm_0++; + } else if (rank == (matrix_m - 1)) { + fm_1++; + } else { + fm_rest++; + } + } + + /* Compute chi_square */ + term1 = ((fm_0 - (0.2888 * num_matrices)) * + (fm_0 - (0.2888 * num_matrices))) / + (0.2888 * num_matrices); + term2 = ((fm_1 - (0.5776 * num_matrices)) * + (fm_1 - (0.5776 * num_matrices))) / + (0.5776 * num_matrices); + term3 = ((fm_rest - (0.1336 * num_matrices)) * + (fm_rest - (0.1336 * num_matrices))) / + (0.1336 * num_matrices); + + chi_square = term1 + term2 + term3; + + p_value = exp(-chi_square * 0.5); + + return (p_value); +} + +/*** + *** Tests for isc_random32() function + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM32); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM32); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM32); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random32_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM32); +} + +/*** + *** Tests for isc_random_bytes() function + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM_BYTES); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM_BYTES); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM_BYTES); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_bytes_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM_BYTES); +} + +/*** + *** Tests for isc_random_uniform() function: + ***/ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_monobit) { + UNUSED(state); + + random_test(monobit, ISC_RANDOM_UNIFORM); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_runs) { + UNUSED(state); + + random_test(runs, ISC_RANDOM_UNIFORM); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_RANDOM_UNIFORM); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_random_uniform_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_RANDOM_UNIFORM); +} + +/* Tests for isc_nonce_bytes() function */ + +/* Monobit test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_monobit) { + UNUSED(state); + + random_test(monobit, ISC_NONCE_BYTES); +} + +/* Runs test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_runs) { + UNUSED(state); + + random_test(runs, ISC_NONCE_BYTES); +} + +/* Block frequency test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_blockfrequency) { + UNUSED(state); + + random_test(blockfrequency, ISC_NONCE_BYTES); +} + +/* Binary matrix rank test for the RANDOM */ +ISC_RUN_TEST_IMPL(isc_nonce_bytes_binarymatrixrank) { + UNUSED(state); + + random_test(binarymatrixrank, ISC_NONCE_BYTES); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_random32_monobit) +ISC_TEST_ENTRY(isc_random32_runs) +ISC_TEST_ENTRY(isc_random32_blockfrequency) +ISC_TEST_ENTRY(isc_random32_binarymatrixrank) +ISC_TEST_ENTRY(isc_random_bytes_monobit) +ISC_TEST_ENTRY(isc_random_bytes_runs) +ISC_TEST_ENTRY(isc_random_bytes_blockfrequency) +ISC_TEST_ENTRY(isc_random_bytes_binarymatrixrank) +ISC_TEST_ENTRY(isc_random_uniform_monobit) +ISC_TEST_ENTRY(isc_random_uniform_runs) +ISC_TEST_ENTRY(isc_random_uniform_blockfrequency) +ISC_TEST_ENTRY(isc_random_uniform_binarymatrixrank) +ISC_TEST_ENTRY(isc_nonce_bytes_monobit) +ISC_TEST_ENTRY(isc_nonce_bytes_runs) +ISC_TEST_ENTRY(isc_nonce_bytes_blockfrequency) +ISC_TEST_ENTRY(isc_nonce_bytes_binarymatrixrank) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/regex_test.c b/tests/isc/regex_test.c new file mode 100644 index 0000000..12051f1 --- /dev/null +++ b/tests/isc/regex_test.c @@ -0,0 +1,2335 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef HAVE_REGEX_H +#include <regex.h> +#endif /* ifdef HAVE_REGEX_H */ + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/commandline.h> +#include <isc/print.h> +#include <isc/regex.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test isc_regex_validate() */ +ISC_RUN_TEST_IMPL(regex_validate) { + /* + * test regex were generated using http://code.google.com/p/regfuzz/ + * modified to use only printable characters + */ + struct { + const char *expression; + int expect; + int exception; /* regcomp accepts but is + * disallowed. */ + } tests[] = { + { "", -1, 0 }, + { "*", -1, 0 }, + { ".*", 0, 0 }, + { ".**", -1, 0 }, + { ".*\?", -1, 0 }, + { ".*+", -1, 0 }, + { "+", -1, 0 }, + { ".+", 0, 0 }, + { ".++", -1, 0 }, + { ".+\?", -1, 0 }, + { ".+*", -1, 0 }, + { "\?", -1, 0 }, + { ".\?", 0, 0 }, + { ".\?\?", -1, 0 }, + { ".\?*", -1, 0 }, + { ".\?+", -1, 0 }, + { "(", -1, 0 }, + { "()", 1, 0 }, + { "(|)", -1, 0 }, + { "(a|)", -1, 0 }, + { "(|b)", -1, 0 }, + { ".{", 0, 0 }, + { ".{1", -1, 0 }, + { ".\\{1", 0, 0 }, + { ".{1}", 0, 0 }, + { ".\\{1}", 0, 0 }, + { ".{,", 0, 0 }, + { ".{,}", 0, 0 }, + { ".{1,}", 0, 0 }, + { ".\\{1,}", 0, 0 }, + { ".{1,\\}", -1, 0 }, + { ".{1,", -1, 0 }, + { ".\\{1,", 0, 0 }, + { ".{1,2}", 0, 0 }, + { ".{1,2}*", -1, 0 }, + { ".{1,2}+", -1, 0 }, + { ".{1,2}\?", -1, 0 }, + { ".{1,2", -1, 0 }, + { ".{2,1}", -1, 0 }, + { "[", -1, 0 }, + { "[]", -1, 0 }, + { "[]]", 0, 0 }, + { "[[]", 0, 0 }, + { "[^]", -1, 0 }, + { "[1-2-3]", -1, 0 }, + { "[1-22-3]", 0, 0 }, + { "[+--23]", 0, 0 }, + { "[+--]", 0, 0 }, + { "[-1]", 0, 0 }, + { "[1-]", 0, 0 }, + { "[[.^.]]", 0, 0 }, + { "[^]]", 0, 0 }, + { "[^^]", 0, 0 }, + { "[]]\?", 0, 0 }, + { "[[]\?", 0, 0 }, + { "[[..]]", -1, 0 }, + { "[[...]]", 0, 0 }, + { "[[..5.]--]", -1, 0 }, + { "[[.+.]--]", 0, 0 }, + { "[[..+.]--]", -1, 0 }, + { "[[.5.]--]", -1, 0 }, + { "[1-[=x=]]", -1, 0 }, + { "[[:alpha:]]", 0, 0 }, + { "[[:alpha:]", -1, 0 }, + { "[[:alnum:]]", 0, 0 }, + { "[[:alnum:]", -1, 0 }, + { "[[:digit:]]", 0, 0 }, + { "[[:digit:]", -1, 0 }, + { "[[:punct:]]", 0, 0 }, + { "[[:punct:]", -1, 0 }, + { "[[:graph:]]", 0, 0 }, + { "[[:graph:]", -1, 0 }, + { "[[:space:]]", 0, 0 }, + { "[[:space:]", -1, 0 }, + { "[[:blank:]]", 0, 0 }, + { "[[:blank:]", -1, 0 }, + { "[[:upper:]]", 0, 0 }, + { "[[:upper:]", -1, 0 }, + { "[[:cntrl:]]", 0, 0 }, + { "[[:cntrl:]", -1, 0 }, + { "[[:print:]]", 0, 0 }, + { "[[:print:]", -1, 0 }, + { "[[:xdigit:]]", 0, 0 }, + { "[[:xdigit:]", -1, 0 }, + { "[[:unknown:]]", -1, 0 }, + { "\\[", 0, 0 }, + { "(a)\\1", 1, 0 }, + { "(a)\\2", -1, 1 }, + { "\\0", 0, 0 }, + { "[[][:g(\?(raph:][:alnu)(\?{m:][:space:]h]<Z3})AAA)S[:space:]" + "{176,}", + 0, 0 }, + { "(()IIIIIIII(III[[[[[[[[[[[[[[[[[[^[[[[[[[[ [^ " + " " + "fX][:ascii:].)N[:a(\?<!lpha:])][:punct:]e*y+)a{-124,223}", + 3, 0 }, + { "(pP\\\\\\(\?<!" + "\\\\\\\\\\\\\\\\\\\\\\lRRRRRRRRRRRRRRRRBBBBBBBBBBBBBBBB))" + "kkkkkkkkkkkkkkkkkkkkk|^", + 1, 0 }, + { "[^[^[{111}(\?=(\?:(\?>/" + "r(\?<(\?=!(\?(\?!<!Q(\?:=0_{Meqipm`(\?((\?{x|N)))))|))+]+]Z)" + "O{,-215}])}))___________________{}", + 0, 0 }, + { "[C{,-218(\?=}E^< ]PP-Ga)t``````````````````````````{138}", 0, + 0 }, + { "[^h(\?<!(\?>Nn(\?#])))", 0, 0 }, + { "[(\?!(\?<=[^{,37}AAAA(AAAAAAAAAAAAA])", 0, 0 }, + { "[^((\?(\?:ms(\?<!xims:A{}(\?{*</H(\?=xL " + "$(\?<!,[})))*)qqqqqqqqqqqqqqqqqq)]" + "33333333333333333333333333333{[:graph:]p)-+( " + "oqD]){-10,}-{247}_______________________X-e[:alpha:][:" + "upperword:]_(______wwwwwwwww " + "/c[:upperword:][:alnum:][:alnum:][:pun(\?{ct:])[:blankcntrl:" + "]})*_*", + 2, 0 }, + { "[(\?<!:lowerprin(\?{t:]{}}){113,})[:punct:]" + "IIIIIIIIIIIIIIIIIIIIIIII", + 0, 0 }, + { "PP)", 0, 0 }, + { "(([^(\?<!((\?>\?=[])p.]}8X[:blankcntrl:],{-119,94})XmF1.{)-)" + "[:upperword:])[:digit:]{zg-q", + 2, 0 }, + { "[^[({(\?#254}))Z[l][x50]=444444444444(4444444444u[:punct:]" + "\?[:punct:(\?!])])", + 1, 0 }, + { "[^[^[^([^((*4[(^((\?<=])Ec)", 0, 0 }, + { "(0)Y:8biiiiiiiiiiiiiiiiiii", 1, 0 }, + { "[^w(\?!)P::::::::::::::(\?#::(\?<=:::::::::]\"\"{}[" + "3333333333333333(\?<=33333(\?!)9Xja][:alph(\?<=a:])xB1)(" + "PX8Cf\?4444)qq[:digit:])", + 1, 0 }, + { "([U[^[^].]^m]/306KS7JJJJJJJJ{})", 1, 0 }, + { "[^[^([^[(\?!(\?>8j`Wg2(\?{,(\?>!#N++++(\?<![++++++)+" + "44444444bA:K(\?<!O3([:digit:]3]}}}}}}}}}}}}}}}}}}}}}}}}LP})" + "S", + 0, 0 }, + { "[({(\?{,(\?(=213}*))})]WWWWWWWWWWWWWWW[:alnum:])", 0, 0 }, + { "[:(\?<=ascii:])", 0, 0 }, + { "[U(\?#)(\?<=+HzE])[:punct:]{-207,170}\?s.!", 0, 0 }, + { "{}z=jU75~n#soD\"&\?UL`X{xxxxxxxxxxxxxxxxxxxx(xxxxxx${-246," + "27}[:graph:]g\"{_bX)[:alnum:][:punct:]{-79,}-", + 1, 0 }, + { "[^{,-186}@@@@[^(\?{@@(\?>@+(\?>l.]}))*\\BCYX]^W{52,123}(" + "lXislccccccccccccccccc)-*)", + 1, 0 }, + { "(x42+,)7=]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]", 1, 0 }, + { "[^(*[:graph:]q/TH\?B(\?{P)]})uZn[:digit:]+2", 0, 0 }, + { "([XXXXXXXXXXXXXXXXXXXXX[(:alnum:][:space:]i%[:upperw(\?=o(" + "\?#rd:])) ", + 1, 0 }, + { "(@@@@)", 1, 0 }, + { "{-18,}[:as[(\?>^[cii:]]{}>+{-46,}{,95}[:punct:]{}" + "99999999999999])-{-134}'sK$" + "wCKjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj", + 0, 0 }, + { "(l[:alpha:(\?!]))", 1, 0 }, + { "[[^(\?{]|JJ[:alph(a:]X{})B^][:lowerprint:]n-219{-32}{19,105}" + "k4P}){,-144}", + 0, 0 }, + { "[[^]P[:punct:][:alpha:][:xdigit:]syh]|W#JS*(m<2,P-RK)cA@", 1, + 0 }, + { "([^((\?({\?<=)}){[^}^]{}])^P4[:punct:[]$)]", 1, 0 }, + { "([(\?#:(\?{space:]}):{}{-242,}n)F[:alpha:]3$)d4H3up6qS[:" + "blankcntrl:]B:C{}[:upperword:]r", + 1, 0 }, + { "([(\?:]))[:digit:]mLV.{}", 1, 0 }, + { "[^PPP-[]{[,50}{128,}]111111111111111]p", 0, 0 }, + { "[^([^([^([[^[([^[^[[2[[[[[[[[[[[[[^[[[[(\?(\?{:[[[[[[(\?([-[" + ":ascii:]--*)", + -1, 0 }, + { ")!F^DA/ZZZZZZZZZZZZZZZZZZ", 0, 0 }, + { "[[[[[[[((\?=\?(\?>([[[[[[[^[[[[(\?()[[[K(\?#))])))]7Y[:" + "space:]{,-96}pP)[:ascii:]u{-88}:N{-251}uo", + 0, 0 }, + { "t[:x(\?<=digit:])eYYYYYYYYYYYYYYYYYY{,-220}A", 0, 0 }, + { "[[({10,}[:graph:]Pdddddd(\?#X)])[:alnum:(]]L-C){,50}[:" + "blankcntrl:]p[:gra(ph:]){66,}", + 0, 0 }, + { "[^[^]*4br]w[:digit(\?::]n99999999999999999)P[:punct:]pP", 0, + 0 }, + { "[:digit:]{67,247}!N{122})VrXe", 0, 0 }, + { "[:xdigit:]^[:xdigit:]Z[:alnum:]^^^^1[:upperword:(\?=])[:" + "lowerprint:]*JJ-", + 0, 0 }, + { "[[(\?imsximsx:^*e(){,3[6}](V~\?^[:asc(\?!ii:]I.dZ))]$^" + "AAAAAAAAAAAAAAAAAAAAAAAA[:space:]k)]", + 1, 0 }, + { "W{,112}[:lowerp(\?<!rint:]$#GT>R7~t'" + "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"9,O).", + 0, 0 }, + { "[^{6((\?>\?:4}(\?<=G))f)" + "KKKKKKKKKKKKKKKKKKKKKKKKKKKKKpppppppp(\?=ppppp]{,-101}|[:" + "blankcntrl:]Z{-182})", + 0, 0 }, + { "([:punct:]@^,,,,,,,,,,,,,,,,,,,,,,,,,,0\?:-o8NPIIIIIIIII)" + "pPKKKKKKKKKKKKKKKKKKKK", + 1, 0 }, + { "([^[[^[^]]]])", 1, 0 }, + { "[([^[(333\"(\?#\\\\[)(\?isx-x:\"Tx]')", 0, 0 }, + { "[[n>^>T%.zzzzzzzzzzzzzzzzz$&|Fk.1o7^o, " + "^8{202,-12}$[:alnum:]]G[:upperword:]V[:xdigit:]L|[:" + "upperword:]KKKKKKKKKKKKYX\"\")xJ " + "~B@[{,-68}/][:upperword:]QI.", + 0, 0 }, + { "[^[]tN^hy3\"d@v T[GE\?^~{124,10(\?{2}]})\?[:upperword:]O", 0, + 0 }, + { "d.``````````````````````````[:up(\?=perword:]" + "RRRRRRRRRRRRRRR)", + 0, 0 }, + { "[Z{{{{{{{{{{{{{(\?={(\?<!{{{{{{{{{(\?>{{J6N:H[tA+mN3Zmf:p\?]" + "\?){-181,82}S4n.b[:lowerpri(\?{nt:]|" + "ggggggggggggggggggggggggggggggg}))4)", + 0, 0 }, + { "[^((/////[^////[^/////////[(^/////]fI{240}{-120}+]R]GA)", 0, + 0 }, + { "[-(\?#.)(\?())[:alpha:](\?={(\?#}r)[:space:]PPW]o)", 0, 0 }, + { "[:lowerp(\?{rint:]})201{46,}[:a[^scii:]0Q{37,}][:blankcntrl:" + "]1331", + 0, 0 }, + { "[^(\?!(\?#)\\GIwxKKKKKKKKKK'$KKKKKKKK]l)bbb^&\?", 0, 0 }, + { "[:ascii:]*[:sp(\?<=ace:])", 0, 0 }, + { "({-66,}Z{})0I{-111,}[:punct(\?():])", 1, 0 }, + { "[[^(\?!()%%%%%%%%%%%%%(\?:%%%%%%%%%%%%%%%%)t(\?{VX>B#6sUU(" + "\?<!UUUUUU(\?=UUU[^UUUUUUUUUUUU(\?((\?:UPPPPPPPPPPP)" + "PPPPPPPPPPPPPPP]ffffffffffffffffffffffff)^[:space:]" + "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww{243}9[:lowerprint:]Dv[:" + "graph:])][:blankcntrl:]V%E[:graph:]})[:space:]{-83,}cQZ{}4{-" + "23,135}", + 0, 0 }, + { "({,-76[}]O[:xdi(\?<!git:])\?5))))))))\?d[:lowerprint:]" + "b666666[:graph:]c", + 1, 0 }, + { "{}{-145,}[:(\?(spa)ce:])f", 0, 0 }, + { "[([^].{116,243}]T*[[^:punct(\?[{[^:(\?<!]]8()])[:alnum:])})]" + "N{}{,243}*[n]][:graph:]", + 1, 0 }, + { "[^w]8888888888888888_________(__________[:ascii:]BdqTE$^0|" + "MNto*i#############[^#################])", + 1, 0 }, + { "[^[[[<[()\?]GGG{,26[}[:alnum:]SSSSS.gggggggg[:graph:]" + "CCCCCCCCCCC{79,}{138,191}][:di(git:]u]@]" + "JJJJJJJJJJJJJJJJJJJJJJJ[:graph:(\?:][:alnum:]])[:alnum:])]", + 0, 0 }, + { "[^(((BBBBBBBBBB(\?>BBBZvvvvvvvvvv(\?m(sximsx:vvv)iiiiiiii)))" + "j>Rs:Sm]0MMMMMMMMMMM|@F)Y]*^#EEEEEEE)*", + 0, 0 }, + { "([^([(U(\?!)<<<<<<<<<<(\?#<<<<(\?<!<<<)(\?=L.{73,})+]n9U}fk%" + "Jn}'b Na<%yyyyyyyyyyyy)){-198,}]))[:space:].pP361U]3s@u_9AU " + "Te/{s`6=IMZdL1|.ySRo", + 1, 0 }, + { "[[((\?<=\?>(\?#){}]{}`){1,82}){-143[,}]^G", 0, 0 }, + { "[:digit:]W|[:up(\?<!perword:]{,-101}llllllllllllllllll[:" + "upperword:])mmYYYYYYYYYYYYYYYYYYYYYYY*", + 0, 0 }, + { "@NHy)", 0, 0 }, + { "([^[^]][:alnum:]222[^22222222(\?{2222222222222222][:lo(\?:" + "werprint:][:xdigit:]^[:blankcntrl:]s+N)[:alpha:]-" + "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNWxxxxxxxxxxxxxxxxxxxxxxxxxxD[" + ":space:]U)TTTTTTTTTTfffffffffffzzzzzzzzzzzzzzzzzzzzzzzzz})", + 1, 0 }, + { "[^[^[[^[][^[]pP([^\?[^<=(\?=]){158,})]]]][:digit:]]" + "K22222222222p^dUKJ`\">@]", + 1, 0 }, + { "[^[^[(\?imsximsx::p(\?{unct:][(\?>:ascii:]5w)]{159}\\Q\?@C]" + "4(44444444}[^)|)[:graph:]]C:b)", + 1, 0 }, + { "[^[[(tYri[W<8%1(\?='yt][:lowerprint:[]))1r]][:alnum:][:" + "digit:]{48}{-52,-183}+][:alpha:]r][:upperword:]\?{-105,155}{" + "-55,-87}pPN#############################{63,232}]", + 0, 0 }, + { "[*(\?>L(\?<(\?>=))]&&&&&&&(&&&&&&&&&&&&&&&&&&))[|WIX]{-62,-" + "114}S K=HW60XE<2+W", + 1, 0 }, + { "(00000000000)z\\\\*t{}R{88}[:alnum:]*", 1, 0 }, + { "(([^(\?=\?gggggg[gLw)]{-250,}[:xdigit:]yZ[:g(raph:]8QNr[:" + "space:][:blankcntrl:]A)][:digit:]D)[:xdigit:])", + 2, 0 }, + { "[^([^,(\?<!]*))]", 0, 0 }, + { "[^(\?{[:alnum:]]}}}}}}}}}}}}}}}}}}}}}}}){-83}", 0, 0 }, + { "WWWWWWWW[:alnum(\?<=(\?#:]{,-1})@OSSS)[:digit:]", 0, 0 }, + { "[^(\?!*]+G)", 0, 0 }, + { "[LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL>s8.>[^{}$(\?(]]XXXXXXX)" + "XXXXXXXXXXXXXX[:alpha:]Whii\?p[:xdigit:])+", + 0, 0 }, + { "(7777[:blankcntrl:])", 1, 0 }, + { "[^C[:digit:]]{}YYYY(YYYYYYYYYYYYYYYY)", 1, 0 }, + { "on|,#tve%F(w-::::::::::::::::::::::::::::*=->)", 1, 0 }, + { "([((\?=(\?!((\?=')))27(<{})S-vvvvvvvvvv(\?=" + "vvvvvvvvvvvvvvvvv[:punct:][:alnum:]}}}}}}}}}}}}}}}}}}}}}}}" + "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPgggggggggggggggggggggggggg(\?#(" + "\?#gggggg<X){}]{-164,61})>+))uQ)W>[:punct:][:xdigit:][:" + "digit:][:punct:]{}[:digit:][:space:]){,-105}=xiAyf}o[:alpha:" + "]akZSYK+sl{", + 1, 0 }, + { "[^[^]/S:Hq<[:upperword:(\?<=]W[:alnum:]X])1973", 0, 0 }, + { "[[^[[^([^VVVV(\?!(VVVVVVVVVVVVVVVVVVVVV[VVVVX][^]2))" + "98ppppppppppppppppppppppppppppppp/////////////////////" + "b.]G{-101,}[:[ascii:]P].=~])AAAAAAAAAAAAA2{-153,}]]]]]]]]]]]" + "]]]]]]]]]]]]]]]]]]]]][:alnum:][:lowerprint:]WN/" + "D!rD]|4444{180}]V_@3lW#lat]", + 0, 0 }, + { "[^[^([^TTTTT(\?:T(\?:T7777{,59}])[:graph:][:ascii(\?<=:]))f]" + "AD{,-43}%%%%%%%%%%%%%%%%)S|[:digit:]FZm<[:blankcntrl:]QT&xj*" + "{-114,}$[:xdigit:]042][:xdig[it:]{-180}027[:alpha:][:ascii:]" + "[:lowerprint:][:xdigit:]^|[:alnum:][^Mi]z!suQ{-44,-32}[:" + "digit:]]", + 0, 0 }, + { ")", 0, 0 }, + { "''''''''''[:a(\?imsxisx:lnum:])P", 0, 0 }, + { "(([{20(\?<=8}[:alnum:]pP$`(\?#N)wRH[:graph:]aaaaaaaaaaaaaa(" + "\?=aaaaaaaaaaaaaaaaP]a)))[:punct:]-\?)A^", + 2, 0 }, + { "[^(.//" + "[:punct:]&-333333333333333333333333333(\?<!33)" + "LLLLLLLLLLLLLLLLL[:alnum:]$1]~8]|^\"A[:xdigit:]\?[:ascii:]{" + "128,}{,-74}[:graph:]{157}3N){-196,184}D", + 0, 0 }, + { "[^($(\?{(\?<=)[#)]})[:space:]]nWML0D{}", 0, 0 }, + { ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,[^]x{213,-93}(\?{A7]V{}})", 0, + 0 }, + { "[k(\?=*)+^[f(])r_H6", 0, 0 }, + { "[(\?#(\?{)]q})", 0, 0 }, + { "([GLLLLLLLLLL(\?!((\?:LLLLLLLL]))C#T$Y))^|>W90DDDDDDDDDDD[^" + "DDDDDDDDDDDDDDDDDDDD]B[:punct:]c/", + 1, 0 }, + { "[^(\?<!)(\?{b}){,199}A[:space:]+++++++(\?!++++++++{36}Tn])", + 0, 0 }, + { "()[:alpha:]a", 1, 0 }, + { "[(\?(:blan)kcntrl:])lUUUUUUUUUUUUUUUUUUUUUUU", 0, 0 }, + { "[^[^(s[[[[[[[[[[[[[[(\?#[[[[[[[)\?`````][:blankcntrl:(\?>]|)" + "p1EmmmmmmmmmmmmmmmmmmmmmmmmmmmmL{-241}666666666666666666666)" + "]^bLDDDDDDDDDDDDD]", + 0, 0 }, + { "[nn(\?<!nnnnn(\?#n8)=````````````````````{41,}]U,cb*%Y[:" + "graph:]).[:alnum:]\\\\\\\\\\gt", + 0, 0 }, + { "()\?5{,-195}lm*Ga[:space:]Y", 1, 0 }, + { "[(\?:].di)c", 0, 0 }, + { "([([^([\?{})Za,$S(\?!p(\?{++(\?##V(\?<!Evuil.2(\?<![^[h|[^']" + "C)*\"]5]", + 1, 0 }, + { "[((^24(\?#4[^Kkj{}))]]{232}47)077[:alpha:]zzzzzzzz{}", 0, + 0 }, + { "[^(\?:[^F]o$h)-iV%]", 0, 0 }, + { "[[^[([((([^(\?{[^((\?=)kaSx(\?imsximsx:w3A[`%+A$I{,62}ns&Y!#" + "ay " + "o9YAo{Y>1((\?>\?#45)Z{,108}{}11111111111111111111111111qqqq)" + "\?][:lowerprint:]mbo#)@", + 0, 0 }, + { "[^iii8(888888(\?<!8^]))s", 0, 0 }, + { "([[(\?(\?:({^]}[)[(r)])G]{,-87}", 1, 0 }, + { "([[^{249,}(\?>(\?=)]]T()[:bl(\?!ankcntrl:]=jjjjjjjjjjjjjjjj-" + ")))t{}[:alpha:]-\":i! Gn[A4Ym7<<<<<<<<<<<<<<<<]", + 2, 0 }, + { "^{}{[^,241(\?#}(\?m(\?ixim:sximsx:]t))+oD)", 0, 0 }, + { "5[(\?#:xdigit:])", 0, 0 }, + { "[^f{(\?>,22(9}[^[^])6KKKKKKKKKKKKK)]RRRRRRRRfuK99999999C}" + "osnNR]BgCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[:blankcntrl:]", + 0, 0 }, + { "[^(\?=U){24,}W-{,17(\?:3[^}]q.nQ#PU_|i$$$$$$$$$$$$$$+)[:dig(" + "\?<!it:]){-98}\?[:upperword:]]", + -1, 0 }, + { "[(\?<=[0(\?!72])euE.]{,-159}[:alnum:]t-:l\?)$" + "yyyyyyyyyyyyyyyyyyyyyyyyyyfffffffffffffffffffffffffff", + 0, 0 }, + { "[^[^]q[:asc(\?imsxmsx:ii:]JJJJJJJJJJJJJJJJJJJJ[:graph:]]$)`#" + "DdY^qqqqqqqqqqqqqqqqqqqqqqqqqqqu>4^4ta[:alpha:]", + 0, 0 }, + { "(((b0HN)q))p5<T())`7JJv{'cv'#L8BNz", 4, 0 }, + { "[pFp2VttBg(\?<=7777777777777|TTTTTTTTTTTTTTT[:space:]Z]^p\"[" + ":blankcntrl:])", + 0, 0 }, + { ")aM@@@@@@@@@@@@@", 0, 0 }, + { "([^[(\?<![^])", 1, 0 }, + { "()Z[:ascii:]", 1, 0 }, + { "(fuPPo)..........................[:xdigit:]{}{,4}*kkkkkkkCx#" + ",_=&~)|.2x", + 1, 0 }, + { "[+(\?<=){}++++++[:alnum:](\?=+]s)[:alnum:]~~~~~~" + "XXXXXXXXXXXXXXX.[:digit:]", + 0, 0 }, + { "[{}[^^(\?(]))CCCCCCCCCCCCCCCCCCCCEg2cF]{}3", 0, 0 }, + { "([[[^[^[^([[^[^([(\?<=G[[)=(\?!===(\?isximsx:==(\?#==[^=====" + "(\?{==================$T[[^^u_TiC.Fo.02>X)uH]$})354b[:alnum:" + "]]]EVVVVVVVVVVVVVVVVVVVVVVVVVVVVVz[:digi(\?(t:][:upperword:]" + ")", + 1, 0 }, + { "([:blankcntrl:]t-){121,}[:ascii:]444444{}[:graph:]E040", 1, + 0 }, + { "[^{134,}]DzQ\?{-30,191})z,\?1Vfq!z}cgv)ERK)1T/=f\?>'", 0, + 0 }, + { "@v)<yN]'l-/" + "KKKKKKKBBBBBBBBBBBBBMa2eLA[:digit(\?<!:])\"\"e|l$&m`_yn[:" + "blankcntrl:]uuuuuuuuuuuuuuuuuuu[:punct:]", + 0, 0 }, + { "[[999999999999999(\?<=(\?:(\?ixmx:(\?>))])Y]|){,10}\?{}", 0, + 0 }, + { "([[[(\?!^]P-AA[AAAAAA[A[^A)r]+B]])", 1, 0 }, + { "3}|[:ascii:][:punct:]()", 1, 0 }, + { "()dw", 1, 0 }, + { "[N]{})))))))))))))))))))))))", 0, 0 }, + { "[[[^([[(\?()(\?#)++([^\?{+++[^+++++++++++(\?!+(\?=+++++++r9/" + "n]N7{-219}{-91}pP[:punct:]T]mROm+~[:digit:][:digit:])Y:", + 0, 0 }, + { "[^'Pu[(\?<!D&]_a[:alnum:]E<,F%4&[:xdigit:])][:lowerprint:]", + 0, 0 }, + { "tttt(tttttttttt*uKKUUUUU)", 1, 0 }, + { "([:ascii:]GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG)+kX______________{" + "}GGGGG\?TUH3,{67,77}|[:graph:]C{,-136}{}[:upperword:[]{,-6}&" + "]T84]n={C", + 1, 0 }, + { "[:upperword:]DC[:u(\?<=pperword:]*d`H0\?m>~\?N|z#Ar--SO{,-" + "141}076)G\?{,-110}M+-[:alpha:]", + 0, 0 }, + { "{,-214}{,10(9})", 1, 0 }, + { "([^xxxxxxxxxxxxxxxxxMMMMMMMMMMMMMMXW])].[:punct:]Q`{-63,63}" + "Uua[:alnum:]\?OQssb#L@@@@@@@@(@@@)[:graph:]", + 2, 0 }, + { "[[^(\?!```[^``````````````(\?<=``(\?>````````M/////(\?!/////" + "///////////////" + "[^GD!|#li]~)*.$]))Tq!]C[:lowerprint:]Qk[{}]]" + "JJJJJJJJJJJJJJJJJJJJJJJ{e])c", + 0, 0 }, + { "$[5(7ES])[:xdigit:]%{MRMtYD&aS&g6jp&ghJ@:!I~4%{" + "P\?0vvvvvvvvvvvvvvvvvvvv\\\\\\\\\\\\\\\\\\\\\\\\x54[:" + "lowerprint:][:upperword:]", + 0, 0 }, + { "[((([(\?((\?>[:alnum:][):as(\?<!cii:(\?:]Re))K|)|^){-28,89}" + "l<H.<H:N)QKuuuuuuuuw8E136P)^)[:ascii:]][:xdigit:]-", + 0, 0 }, + { "(pjvA'x]=D\"qUby\\+'R)r\?C22[:ascii:]", 1, 0 }, + { "[]*b~y C=#P\"6(gD%#-[^FBt{}]${-244}", 0, 0 }, + { "[:up(\?!pe(\?=rword:])lA-'yb\"Xk|K_V\"/" + "@}:&zUA-)W#{-178,-142}(){-202,}", + 1, 0 }, + { "()1.WldRA-!!!!!!!!!!!!!!!!!", 1, 0 }, + { "lZZZZZZZZZZZZZZZ(Z[:al(\?:num:])" + "ttttttttttttttttttttttttttttttg.)6$yyy", + 1, 0 }, + { "[([^([^[^(([([^[^(([[$(\?{P(\?=(\?<(\?!=(\?#P[^Y])<GA[:" + "ascii:][(\?#(\?<!:alpha:](B{100,})]}))\?)XU=", + 1, 0 }, + { "[[dVw{6(\?{9,}2222kkkkkkkkkkkkkkkkkkkkkkkkkk|{}*E]]{}SB{35}-" + "w%{eh})<{-178,}", + 0, 0 }, + { "(D(~))", 2, 0 }, + { "[(:alpha:]{,90}Z|)[:ascii:]Du\?[:grap[^h:]^w+|{}][:ascii:]", + 0, 0 }, + { "[:p(\?<=unct:]kkkkkkkkkkkkkkkkkkkk)", 0, 0 }, + { "{}[:((\?<!dig((\?#it(\?#:]())p))ZZZZZZZZZZ[:blankcntrl:]){}{" + "-124,})[:ascii:]", + 1, 0 }, + { "[[:graph:]{168}lRRRRRRRRRRRRR(\?#RRRRRRRRRRRRRRRRR)rrrr(\?(" + "rrrrrr)rrrrrrrS[(\?<!@f)6>{,-49})q${98,}J\?]){", + 0, 0 }, + { "([:pu(\?(nc)t:]F{-32,-102}+)\?cpP[:lowerprint:].^)", 1, 0 }, + { "([{}{210,-238}]1:h)", 1, 0 }, + { "([]QQQQ[QQQQQQQQQQQQQQQQQQ][:digit:]Z{-20,}Slllllll[:space:]" + "C^(@{-174,-156}fx{cf2c}{-242,}rBBBBBBBBBBBBBBBBBBc[:alpha:]" + "N\?))$[:graph:][:ascii:]P+nnnnnnnnnnnnnnnnnnnnnnn1N$r>>>>>>>" + ">>>>>>>>>>>>>>>>>(>>{,88}{,-234}__________)[:upperword:]R.[:" + "alnum:][:lowerprint:]^}\"", + 3, 0 }, + { "([^(\?=]-))$", 1, 0 }, + { "([:ascii:]\?,D[:upperword:][:xdigit:]tttttttttttt[^tt(\?<!" + "ttttttttt21f|.(pP[:punct:])])rrrrrrrr)", + 1, 0 }, + { "([{1(\?=16}iiiiiiiiii((\?<=iiiiiiiiiiiiiiiiii|ZZZZZZZZZZZ(" + "\?(\?#{ZZZZZZZ))c}))<<<<<(\?#<<<<<<<<<<<d7CVq8]w{-148,-168}" + "\\Gp){-230,}D3", + 1, 0 }, + { "[^8888(88888888888EX].[:alnum:]){}", 0, 0 }, + { "([^][^)2]-[:lower(\?=print:]{,79}[:graph:]n)", 1, 0 }, + { "[bSi\?x_mp(C)0{64}[:space:]hhh(\?(hhh)hhL){5,130}'w\"$l&[:" + "xdigit:][:alpha:]IIIIIIIIIIIIIIIIIIIIIII+-SOOOOOOOOOOOO " + " (\?( ) ]f)ed", + 0, 0 }, + { "[[^[(^(C.Jl[^X&Rb64a+Sd])'m[:alpha:])]]]{134,}", 0, 0 }, + { "()L", 1, 0 }, + { "[[(({224,(\?#88})@======(\?!=========(\?{=)PPP)i^@p(\?([:" + "punct:]})^^[^^^^^^^^^^^^^^^^^^^^^@)m]|{CS{,-3}168)-[:xdigit:" + "][:upperword:]hnD=Bns)z)AAAAAAAAAAAAAAAAAAAAAAA[^A{}" + "ccccccccccc)SZ]Q-p.sD]]+P", + 0, 0 }, + { "[[^[^]{135,}66666666666666666666[6(666i2M9.!uhmT\?JMm.*(\?!+" + ")[:alpha:]eeeeeeeeeeeeeeeeeeeeeeeeeee]]])ZZ[:blankcntrl:][:" + "ascii:]", + 0, 0 }, + { "(13[3Ux>{,10}[(\?<=:xdigit:]))PL9{-89,-181}F'''''''''", 1, + 0 }, + { "[^.|(\?{af]})^$XE!$", 0, 0 }, + { "(WWWWWWWWWWWWWWWWWWWWWWWWWWWW#J)", 1, 0 }, + { "({}}M7we-216)L[:digit:][:upperword:]", 1, 0 }, + { "([:aln[^u(\?=m:]))].z", 1, 0 }, + { "([:alpha:]{(92})%6{41,136})Vij@[:alnum:][:lowerprint:]", 2, + 0 }, + { "[[[++(\?{+++{}})n{{137,}{51,-177}Z[]M*[:ascii:]{(-29,-47}2)$" + "e^{,-195}{-156,}^]{}{-225,69}A]{-222,}{,20}m[:blankcntrl:]", + 1, 0 }, + { ")l)[:alnum:][:graph:]g8TTTTTTTTTTTTTTTTLLLLLLLLLLLLLLLLL", 0, + 0 }, + { "[([(\?<=.(\?{)/})mmmmmmmm(\?(mmmmm]{-154,-176}*S)I]", 0, 0 }, + { "[(([{(\?(\?<!im(\?imsix:sim(sx:,141}])D)l{,42}ttttt[(\?::" + "punct:])){-162,-141}{-26,})dU@@@@@@@@@@@@@@@ " + "S)\\A\?w|VVVVVVVVV)X.kN{,21}{-208,-52}>[:lowerprint:][:" + "ascii:]e-]]]]]]]]]]]]]]]]]]]]]", + 0, 0 }, + { "[^({}(){(66(\?=,}[^]'''''QQQQQQQQQ).P#>^){86,168}Z[(\?<!:" + "lowerprint:]{-166,-70}<k", + 0, 0 }, + { "APP[:alpha:][:alnum:]nd[:upperword:(\?(]^" + "xxxxxxxxxxxxxxxxxxx)xxxxxxxxx{-70}[:punct:]l)U-", + 0, 0 }, + { "[^(.\"od~(6({[^(\?<!228}\?)\?)######(\?:#########z " + ")c(\?<!aQ`(\?{UKSwu[})][^-17]{11,}}][:ascii:]))^RiH+WyspP[" + "qi&)=p6])[:space:]{-221,}]6p", + 0, 0 }, + { "{-78}()[:xdigit:]{155}{,-92}", 1, 0 }, + { "[(\?>Q{,147}_____________(\?!______uuuuuuuuuuuuuTr]){74,179}" + "{}){,103}{-209,16}*RRRRRRRRRRRRRRRRw{,87}9{144}[:ascii:]'<" + "Ab", + 0, 0 }, + { "([666c] {-171}yc,8-k_)EEEEEEEEEEEEEEEEEEEEE<", 1, 0 }, + { "[^(\?>(\?<!)2(\?imim:)6HwN)^|fc!(\?(d]75))065)G", 0, 0 }, + { "[[^xDB[:alnum:][:xdigit:]][:digit:]jW]([:alpha:])", 1, 0 }, + { "[ds~T+[x55[:digit:]X[JJJJJJJ.[(\?::upperword:]){,-14}][:" + "xdigit:]bbbbbbbbbbb", + 0, 0 }, + { "[qqqqq(\?<=qqqq(\?(qqq)^G[):ascii:]])W", 0, 0 }, + { "[:space:]JJJJJJ[:alph(\?<!a:]|[:ascii:(\?(])[:x)digit:]- " + "XSstG[:g(\?>raph:])^)Ny6RF_ndoU9@*rxW{4,41}4{}", + 0, 0 }, + { "[:punct:]{162,}j[:aln(um:].....................[^...]\?>z[:" + "l[owerprint:]){55,222}]", + 0, 0 }, + { "(>vWa)OXcccccccccccccccccccccccc[:alpha:]C{,-10}81|m1D^T)[:" + "lowerprint:]''''[:alpha:]l", + 1, 0 }, + { "(XZcgM/UI-/" + "mZq-222){-85,-196}[:alpha:]{114}rrrrrrrrrrrrrrrrrrrrrrrr{," + "157}ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZLkD-&&&&&&&&&&&&&&&-][:" + "alnum:]{}{,111}[:digit:]", + 1, 0 }, + { "[^(\?:]MMMMMMMMMMMMMMMMMMMMMMMMMMM)cK[" + "KKKKKKKKKKKKKKKKKKKKKKKK]P{146}", + 0, 0 }, + { "([^[^wqesa)n\?L(\?<=FH+G[^rCGmfD]w)m1D\"%}]])", 1, 0 }, + { "[((\?:[^.HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH|S)xd)*[:space:](])[" + ":xdigit:]ngr'G#/B]-----------------------------", + 0, 0 }, + { ")[:lowerprint(\?<=(:]l))G p", 0, 0 }, + { "[^[^(\?<(\?<(=(\?imsximx:![(((\?<!\?(^))\?]^)[:xdigit:][:" + "graph:]{-104,})Gf+GD*qc)c]f))])", + 0, 0 }, + { "[^([\?())P[:alnum:]w]{-186,-139}-[:space:]RN3w[Fmvpl[:space:" + "][:digit:]&&&&&&&&&&&&}(\?#}}}}}}}}}}}}}}}}}}}])z", + 0, 0 }, + { "([[^^*C[()f][(\?=:punct([\?#:]o)]V)]%%%%%%%%%%%%%%%%%%%%%%%%" + "%%%%%%[^x{1f948})]]", + 1, 0 }, + { "[(:xdigit:])zE", 0, 0 }, + { "[:pu(\?(nc)t:])(a*){-51}", 1, 0 }, + { "[^(.NKKKKKKKKKKKKKKKKKKKKKKKK-[:upperword:][:space:]`MPi>", + -1, 0 }, + { "Nvvv[vv.][:alnu[^m:]+|Crrrrrrrrrrrrrrrrrrrrr[:xdigit:]j1n)v#" + "]", + 0, 0 }, + { "[^#}[(\?>:alnum:]).QQQQ[^QQQQQQ!!![!!!!!!!-s.n]se]{-238,}Tf]" + "p4721", + 0, 0 }, + { "([((\?#\?<=)+)Hr:-H]z[:graph:].{}oooooo(ooooooooo][:punct:]" + "k<gXG@@@@@@@@@@@@@@@@@@@{,-176}){}L`)$", + 2, 0 }, + { "({,249}{-73,}Z&&&&&&&&Ds35MB<v)qqqqqqqqqqqqqqqqqqqqqqqqq", 1, + 0 }, + { "[^.N][:blankcntrl:]))))))))))))))))))))))))))))))", 0, 0 }, + { "(()*){198,}", 2, 0 }, + { "{-237,}220{}[:ascii:]```````(`````````````\?{-115,185}){,-" + "18}[:punct:]'|Kk", + 1, 0 }, + { "[(\?()])", 0, 0 }, + { "([(\?#[:alnum:]CQ)}}}}}}}}(\?>}}}}}}}(}}}}}\?310[|))xA5r][[^" + ":ascii:]^{,-156}{])CCCCCCCCCCC-145]FzwOD_u\?", + 1, 0 }, + { "[^[^[]{-163}{(-203}[(\?!:upperword:]PPGjZ[:xdi(\?=git(\?#:]{" + "-73}s)qqqq(qqqqqqqqqqqqqqqqqq{173,210}[:xdigit:(\?<(\?>=]WW[" + "^WWWWWWW\?*O)))Q){}08)[(\?(\?<=#:blankcntrl:]{90,}]U)])L)" + "ooooooooooooooooooooooooooox--^c[:ascii:]])s)", + 2, 0 }, + { "[(\?!:punc(\?imximx:t[^:]4F<}!)]'M-)tKKKa4904", 0, 0 }, + { "[^^{}\\(\?<!\\\\\\\\\\\\\\\\\\(\?#\\\\\\\\[:punct:](\?>)" + "T000000000(\?(000)00000))+])", + 0, 0 }, + { "L[:p(\?#unct:])", 0, 0 }, + { "[:upperw(\?<!ord:])", 0, 0 }, + { "@$\"\"\"\"\"\"\"[\"\"\"\"\"\"\"\"\"\"[^(\"\"\"\"\"(\"\"][]))" + "*U{223,138}*o```````````````(\?=[```````````````]{238}" + "mmmPPPPPPPPPPPPPPP&&&&&&&&&&&&&&&&&&)sF$[:digit:[]]", + 0, 0 }, + { "[^#Txx[xxxlPB(\?><[^U/)]]{}X3333333333(3333333f*])", 1, 0 }, + { "<<<<<<<<<<<<<<<[^<<<<<<<<<.][(\?#:ascii:])[:xdigit:]|^", 0, + 0 }, + { "([:punct:]{}){-167,}{-59,}Pd\"", 1, 0 }, + { "[((\?#{,214})t$)VVV[:xdigit:]{104(\?<=}D][:graph:])|H){1,}{-" + "176,}", + 0, 0 }, + { "[[([[^N,,,,,(\?=,,(\?#(\?:,,,,,,,,,,,[^,,,,,,,,,,]<,~4::_.A]" + "){-52,}-[:alnum:]Pnnnnnnnnnnnnnnnnnn)d", + 0, 0 }, + { "{-18(3,})uT{4,}", 1, 0 }, + { "[^[^[(p+c(\?<!b$))(\?:EU(\?(.][^{}]3[:xdigi[^t):][:punct(\?>" + ":])[])][:s[^pace:]][:alnum:][:alpha:]]kw06E", + 0, 0 }, + { "[^^^^^^JJJJJJJJ(JJ(\?=JJ(.6[:space:]H]{231,}A^eqqq)[:ascii:(" + "\?>(])[(\?>:spa(\?:ce:]xxxxxxxxx)@_t-))" + "138GNNNNNNNNNNNNNNNNNNNNNNNNNN[:digit:]no!`#E\?&[:" + "lowerprint:].)[:graph:]{86,}[:digit:][:alnum:]", + 0, 0 }, + { "[:g(\?<=raph:]a{114,146}(){}0Y[:bl(ankcntrl:])D)\?", 1, 0 }, + { "[^[^]*H{-192,96}S|]G)6B-kLB", 0, 0 }, + { "[[^[^][/" + "NS8`um(\?{82&{((\?{\?<!-[110,-88}]m)})kkkkkkkk$$$$$$$$$$$$[^" + "$$$$$@n%BuK@X!P)y0v!^]YY[YYY[YYYYYYYYYYYYYYYYYY///////" + "{}{{{{{{{{{{{{{oiiii})]8{-2[53}w{82,}]{,245}]{-134}]" + "fffffffffffffffffff]\"I>DW>9tN%{113}{unE", + 0, 0 }, + { "[:(\?(alpha:]`))Y2sCqWQ104", 0, 0 }, + { "(([^()Wcccccccc(\?{cccccccccccccccccc(\?<!c(ccccc[:space:]$)" + "(\?>)FZ{}{}`|||||||||||||*````````````````````````````'=" + "dLQmx/" + "Y.A7j'o}jn{}:})][:punct:]$|,-)!&Y:Ys#" + "ykL7JJJJJJJJJJJJJJJJJJJJJJJJJ8yex>#mv[:punct:](x@)$[:uppe(" + "\?<!rword:])_)", + 3, 0 }, + { "[[(^HHHHHHHHHHHH(\?imsximx:HH(HHHHHH(\?{HH[HH])qjR>9))i})]a!" + "lBW3p{A=or)ShE%[:punct:]{}]5r", + 0, 0 }, + { "[:pu[nc[^t:]]]}}}}}}}[}}}}}}}(\?#}])@@@@@@@@@@@@@@@@@@" + "DDDDDDDDDDDDDDDDDDD\?]xA2\?", + 0, 0 }, + { "(.[:alpha:]xB7[:alnu(\?{m:]})RRRRRRRRRRRRRRRRRRRRRRRRRRRL)[:" + "space:]G\?", + 1, 0 }, + { "[:blan(\?<!(\?=kcntrl:]){71,})!ooooooooooooN", 0, 0 }, + { "()e$$$$$$$$$$$$$$$$$$$$iiiiiiii", 1, 0 }, + { "(b[:ascii:]67777777777777777777777777)({-106}kkk^F----------" + "---------------------{13}A)f00000000sBAddddd{-66}kd!D'", + 2, 0 }, + { "(Q ^])[^lf][:space:][:lowerprint:]\?", + 1, 0 }, + { "[[^]\\S{152}W![:digit:][[^:space:(\?(]=pEhwY][:alnum:][:" + "digit):][:graph:]])QQIC9h-oowf[:xdigit:]{-52}{,190}" + "1111111111111111111fX{-189,226}W", + 0, 0 }, + { "[^(\?!(\?<=)]).h[:as(\?>cii:])[:alnum:]$$$$$[:space:]3$$$$$$" + "$$$$$$$$$$$$$$$$$$$$$$$$$1", + 0, 0 }, + { "[[$zQ================(\?<!=(\?>=========(\?====D[^))|i{}" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?)][:s(pace:]])" + ")]", + 0, 0 }, + { "[^{,-[15(\?#6}]Vwjjjjjjjj[jjjjjjjjjjjjjjjjjjS9999)]q]" + "rWWWWWWWWWWWWWWWW[:punct:]@@@@@@@@@@@@@@@@@@@@@@@@gO[:" + "blankcntrl:]>L[:ascii:]:::::::::::::::::::" + "x11uuuuuuuuuuuuuuuuuuuuuuuuuuuuu{-124,114}[:graph:]C#{tcg[:" + "xdigit:]gZZZZ[:lowerprint:]nA(_{{{{{{{{{{{{{{{{{{{{SS)\\D[:" + "alpha:]", + 1, 0 }, + { "[^(\?())]!T\?[:asc[^ii:]E:4},,]I[^b(\?:n4(njj~+{\?'k{7}{189," + "-194}{ig.[[[[[[(\?#[[[_bs6,JD`1(\?<!WBo]F+{d*VO22z2K1][:" + "xdigit:]))Suuuuuuuuuuu[^u{,117}\?YYYYYYYYYYYYYYYYYYYYYYYYB^]" + "|q]:eY1GGGGGGGGGGGGGGGGGGGGGGGGGGGGe\?)bU[:punct:]", + 0, 0 }, + { "[\?UA(\?:]\?)[:xdigit:]A^mmmmmmmmmmmmmm>>>>>>>>>>>>>>>>>>>>>" + ">>>>>>>[^>>>(\?(>)){,-165}]", + 0, 0 }, + { "([^[][^n(\?{[[p]#})|][^]L|66666666666[:graph:]][:graph:]2[:" + "xdigit:][:space:]9b})[:digit(\?imsximsx::]+PZ):{}|E)[:" + "xdigit[^:]|>]^[:alpha:]::::::::[:ascii:]````[:ascii:]:", + 1, 0 }, + { "[:lowerprint(\?<!:])", 0, 0 }, + { "[[^[]{-47}[:lowerprint:][:punct:]L[(\?::g(raph:]lY[:alnum:])" + "qWYU)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}[c%$dp5[:alnum:]DDDDDDDD^" + "^%&{,-94}E]{-8,175}[:alpha:]-.^[:digi(t:]CCCC(CCCCCCCCC])." + "ax72)", + 1, 0 }, + { "[[^($$$$$$$$$$$$$$$$$$[^$I((\?{\?(u)\"YuK " + "ZpOHq[!(\?>t|LQT(|)L[(:ascii:])", + 0, 0 }, + { "[^[^([:graph:](QpPdyDQ`[:alpha:](.X[:digit:]wwwwwwwwwwwwww(" + "\?imxims:wwwwwwwe(\?<!z)ONNN(\?#)[^])[:space:](KKKKKKKKK{" + "113,}327[:xdigit:]k)]CeeeeeeeeeeeeeeeeeMMMMMMMMMMMMMMMMM)[:" + "lowerprint:]]HHHHHHHHHHHHHHHHHHH]]]]]]]]]]]]]", + 1, 0 }, + { "[Q(r(\?=)v]dm[:alnum:][:b(\?{lankcntrl:][:xdigit(\?=:])})P[:" + "graph:]bd/Rx){50}{-150,-172}", + 0, 0 }, + { "[(\?(im(\?:sxims:))9]))L", 0, 0 }, + { "[[^[(\?{^Z][^0[:alpha:]]\\XB*{-151}t})][:alnum:]]", 0, 0 }, + { "[([(D\?/////////////////////.'yvYysU&5AU-]kV)*){,123}z]", 0, + 0 }, + { "[:alnu(\?{m:][:a(\?=lpha:][:alpha:])n}))7[:ascii:][:xdigit:]" + "[:punct:]-", + 0, 0 }, + { "[^[:graph:]IIIIIIIIIIIIIIIIIIIIIII][:sp(\?<!ace:])", 0, 0 }, + { "[[[(\?=[[[cDD(\?<!D(\?:DDDDDDDDDDDD(\?<=DDD(DDDDDD(\?:" + "DDDDDDD(\?<=D(\?()])rvp{243,}D$<[:space:]([:lowerpr)int:])])" + "Ea{}U[:upperword:][:xdigit(\?#:]or}Z+34gD{/P NJ", + 1, 0 }, + { "[^(,H>)*d2K0DNX5)T(].)[:digit:].", 0, 0 }, + { "([:punct:(\?#])})JJJJJJJJ[:xdigit:]" + "PPUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU.......................0hSk{" + ",89}[:xdigit:].[:xdigit:]Z", + 1, 0 }, + { "(LGTTTTTTTTTTTTTTTTTTTTTTTTTT[:alpha:]){-106,113}[:punct:]d|" + "[:digit:]kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk\?wP", + 1, 0 }, + { "([^[^<N_-k\?{(\?#18}]i]::::::::::::::::::::::::::)1+LLLLn{}/" + "){-198}", + 1, 0 }, + { "([[^(AAAAAAAAAA(\?(AAAAA)AAAAf).LzHHHHHHHHHHHHHHHHHHHHH(\?#" + "HHHHH|)[ZEEEEE(\?#EEEEEEEEE(\?<!EEEEEEEEsG)q[:punct:]{}][:" + "upperword:]D)[:space:][:digit:]+e[:ascii:]].i|JJJJJJJJ+n][:" + "xdigit:]Se)P[:lowerprint:]_______________________________.[:" + "punct:]pP{-172,86}iiiiiiiiiiiiiiiiiiiiiiiii){,-178}", + 1, 0 }, + { "([\?=[[^,BDRRPZ{129}*D-[:punct:]]])([:upperword:]ud)\?][:" + "punct:]A", + -1, 0 }, + { "(([(\?#((\?{\?=^])c-)C[:lowerprint:]xvkR}k\")" + "ccccccccccccccccccccNNNNNNN[:alp[ha:]{,93}vhlX:|A]2})nSw)]" + "N.", + 2, 0 }, + { "()g/qzyiV(x3d|A0wllllll){162}[:space:]", 2, 0 }, + { "qqqqqqqqqqqqqqqqqqqqvvvvvvvvvvvv8[:x(\?imsxmsx:digit:][:" + "alpha:]''''''''''''''''''''''''''')", + 0, 0 }, + { "({,226}nf^W=vs$xK^=A=M#b,)V", 1, 0 }, + { "(_T 2BC9N'cccccccccc-87EF#&^eQfDDDn._,m&c`tjAwR " + "#~A)[:(\?imsimx:alpha:])/yHYL6|{-40,47}", + 1, 0 }, + { "[[^]{-8(4,138})z[:xdigit:]{180,}]", 1, 0 }, + { "[([^T____________________(\?:__C(\?<=]-)])+[:ascii:])r[:" + "graph:].----------", + 0, 0 }, + { "[f{}LLLL(LLp((((\?<!((((((((((((((({,56}]BR`{,52}){-22,}\?[:" + "space:]h>Sow", + 0, 0 }, + { "{-179}^[:alpha:(\?!].a'5wacA3\\\\\\\\AAAAAAAA)~^]wC", 0, 0 }, + { ">[:digit:]{,-212}+(`)LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL[:ascii:" + "][:digit:][:space:]", + 1, 0 }, + { "[[^[[^RBW{,255(}(\?(\?>=(W)_]uu][:blankcntrl:])O)]]", 0, 0 }, + { "(C_______________________________)2", 1, 0 }, + { "([/ntf_a3].)", 1, 0 }, + { "[:space:]+[(:upperword:],c7[:asci(\?<=i:]ggggggggggg)[:" + "ascii:]/1$$$$$$$$$$$$$$$$$$$$$$$$$$)", + 0, 0 }, + { "Xq{109}~EEEEEEEE[:upper[^word:]lgB:X(h[:alpha:]B[:space:]].)" + "IkaH@3}}H'yK~\?[:upperw(\?#ord:(\?:]){=================[:" + "blankcntrl:])", + 1, 0 }, + { "(([[^]]$3Xr^$%%%%%%%%%%%%%%%%%%%%%================U[:ascii:]" + ")X).FFFFFFFFFFgO[:punct:]oooooooooooooooooooBC[:blankcntrl:]" + "mmmmmmmmmmmmmmmmmmmm[:lowerprint:]rBM~<HAc#Sb&&&&&&&&&&&&&&&" + "&&&&&&&&&&&&&&Cy", + 2, 0 }, + { "([([([^(\?:)D]-{M#H " + ">rERRRRRRR[^RRRRR(\?>RRRRR])[(\?=^)X]{207,}U])))Z[:" + "blankcntrl:]]yyyyyyyyyyyyyyyy\?", + 1, 0 }, + { "[Q(\?{*[^(\?(\?!!])[:graph:]]})[:alnum:]iE)dGGGGGGG[^" + "GGGGGGGGGG[:xdigit:]w]", + 0, 0 }, + { "[^Z(\?!6(\?(\?><=)[:graph:])]BBBBBBBBBBBBBBBB^)", 0, 0 }, + { "[[^([^[^][[[[[[[(\?({[[(\?(\?imsxmsx(\?imsi[ms:::[[[[[[[[[})" + ")]$)){12,})|:::::::::::::::::::[:lowerprint:]{}{-96,-147}){" + "13,}`[:digit:]]\"^Ca%%%%%%%%%%%%%%%%%%%%%%%%%%" + "UUUUUUUUUUUUUUUUUU]]9", + 0, 0 }, + { "[^(\?(\?(\?#!<=))JLBS\"zi)'''''''''''['''''''''''''" + "piiiiiiiiiiiii(\?<=iiii]])ZZZZZZZZZZZZZZZZZZ[:space:]", + 0, 0 }, + { "({})[:punct:]", 1, 0 }, + { "E9[:blankc(\?{ntrl:]})N", 0, 0 }, + { "[:alph(\?#a:]){198,}sq\?X0B7", 0, 0 }, + { "[^\\\\\\\\(\\\\\\[\\\\\\\\\\\\[(\?<(\?isximsx:={11(\?(9,}" + "\?0])]]))\?FN3M\?{-128,}Z444444)444fbLiVN8)", + 0, 0 }, + { "[[^[^([[[[[[[[[(\?>[[[[[[[[[[[[[[[[[[[[[{53(\?<=,-175(\?>}" + "ggggggggggggggggg%))[:alnum:])[:punct:]" + "kkkkkkkkkkkkkkkkkkkkkkkkk)+" + "Soooooooooooooooooooooooooooooooo](WR+--)x36+llllllllllll{," + "35}]Fqb^=F]KKKKKKaaaaa{,131}", + 1, 0 }, + { "(g\"Ssqw<&{Cl{82,}Mdf|9cIlmCW{}[:digit:]4C{}[:alnum:]PP)", 1, + 0 }, + { "OOOOOOOU[*evVIIIIIIIIIIIIIIIII(\?#(\?#IIII)]PP[:xdigit:]" + "2222222222222222[:xdigit:]Kx)p[:digit:]", + 0, 0 }, + { "([[{248,16(\?=5(\?#}][:alpha:])|[:p(\?!unct:(\?(]", 1, 0 }, + { "[pP((\?=S)(\?#)]$[:aln(\?(um:)]2\?)$GGGGGGGGGGGGGGGGG({-U:c)" + "{-61,}[:ascii:]{-202}G", + 1, 0 }, + { "()$D[:alnum:]", 1, 0 }, + { "[(\?#^]){}[:ascii:]", 0, 0 }, + { "[uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu]FFFFFFFFFFFFFFFFFFFFFF&2e\?)" + "%oP'mc@z2b}n{<b4_Laz^0LLLLLLLLLLLLLLLLLLLLLLL,,,d", + 0, 0 }, + { "{}(^________________''|$)RRRRRRRRRRRRRRRRRRR", 1, 0 }, + { "(H)####################bbbbbbbbbbbbbbbbVSSSSSSSSSSS|" + "tdU\"goeAbPP{-248,81}", + 1, 0 }, + { "[^[(\?ims(\?>xisx:)UHpP*n{}]{}fx14<7OEpE>n2150)" + "8888888888888888]^GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGS", + 0, 0 }, + { "(d)+", 1, 0 }, + { "[^.(\?(>)(\?=e)])al[:space:]x", 0, 0 }, + { "[^256c(\?!]){-19,}", 0, 0 }, + { "Q)", 0, 0 }, + { "[^s\?\?(\?{\?\?\?(\?#\?(\?<!\?\?\?\?\?\?\?\?\?\?\?(" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?{}]F\?j(jjjjjjjjjjjjjjjjjjn)" + "kTI1f[{1|(\?<=^[^+[:digit:]{}^s^))})))T]{-17}{CCCCCCCCCCa{-" + "21,}{,-146}^uZQB]YuLu-|tUGRMz^^", + 1, 0 }, + { "([^.{}.EE[EEEEEEEE(\?<=EEEEEEEEEEEEEEEU]]-@s))$", 1, 0 }, + { "[^([((\?#[#])|a)])[cccccccccccccccc][:digit:]LLLLLLL[:alnum:" + "]}[P%vzl{}^]&", + 0, 0 }, + { "({}[:space:]E)101+A{-35,11}", 1, 0 }, + { "(va:7)u[:alpha:]", 1, 0 }, + { "([^[[rrrrrrrrrr(\?:rrrrrrrrrr(\?<!rrrrrrrrry|D'*AH@a{}\?[:" + "space:][:alpha:]^]$ " + "{-225}[(\?(:as)(\?(>cii:])){-107,-139}6/" + "{^[:upperw(\?imsxmsx:ord:]{,-47} " + "]wuH#nAn)GGGGGGGGGGGGGGGGGr[)]T{91}lJ))[:lowerprint:][:" + "xdigit:][:lowerprint:])]*", + 1, 0 }, + { "()[:space:]~!$[:alnum:]JJJJ[:ascii:]", 1, 0 }, + { "[^(\?<=)-]()k", 1, 0 }, + { "(()W){,8}ea", 2, 0 }, + { "({,-56}5G&&&&rrrrrrrrrrrrrrrrrrrrrrrrrrk.8) hWJ,TM)0Yd-", 1, + 0 }, + { "(Z-fddddddddddddddddddddddd)-{9}", 1, 0 }, + { "[^<[(\?!:asc(\?:i(\?<!i:])F])[:alp(ha:]b))-}Wwx8B", 0, 0 }, + { "[^[^[^([(\?{}(\?=)(\?())-CCCCCCCCCCC(\?=CCCCCCCC(CCCCC(\?:" + "CCCCCCCC(\?{l[(\?!:space:]})[:upperwor(\?:d:]{-27}[:al[^pha:" + "][:xdigit:]^f", + 0, 0 }, + { "[[^]G@>2!+[:punct:(\?<!]{,189}6ZF[:blankcntrl:][:digit:]{," + "214}){-115,-14}l[:upperword:]{101,}Z[:ascii:]Ld&02|c]<0~<bc", + 0, 0 }, + { "(Q)[:digit:]x", 1, 0 }, + { "hT[[:alnum:]\?]O[OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOxFF%^(\?(_" + "LN " + "8uXQT\"*/" + "L)+l)>qQ[^]e[:ascii:]PP()[:digit:]NQ8%6d=&2I{-62,-142}w]].e{" + "}*", + 1, 0 }, + { "{,-219}xxxtEEEEEEEEEEEEEEEE[:pun(\?(ct:])qqq)" + "nnnnnnnnnnnnnnnnnnnnnnnnnnn", + 0, 0 }, + { "[:di(\?>git:])W4", 0, 0 }, + { "([^y])Fkvto$", 1, 0 }, + { "[^($$$$$$(\?!$$$$$(\?{$$$$$$(\?<=$$$$$$$$$$$+===)[:alnum:]" + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM)Z]{}^[:blankcntrl:]--" + "xxxxxxxxxxxxxxx[^xxxxxxx)\?tVG\?{232,81}{121,}xn{,-226}})" + "tttttttttttttttttttttttmu(\?<!&&&&&&&&&&&&&&&&&&&&&&0b]z)$" + "87{,-192}{}{-242,}", + 0, 0 }, + { "l[:dig(\?(it:]|s*)aA[:digit(\?<=:].^.))x[:digit:]", 0, 0 }, + { "[:grap[^(\?#h:]').]Z", 0, 0 }, + { "[:gra[^ph:]t[:digit:]222222222222(22222222222222222H " + "qM]pWZr[:ascii:]-hRb_.)Q{-228,-204}{}", + 1, 0 }, + { "AAAAAAAAAAAAAAA(AA)YeX", 1, 0 }, + { "(!dqqqF*^){(,-79}s!!!!!!!!!!!!)", 2, 0 }, + { "[^(\?msxm(\?#sx:]|)ZHYup)j{95}0L:vXB#')d'DX\?m." + "T034\\\\\\\\\\\\\\\\\\\\\\y5rV{}S", + 0, 0 }, + { "(W*O+yl([\?!P(\?:)I]${}{-195,-14}[:upperword:]{}[:xdi[^git:]" + "[:space:]X[:grap[^h:]~]zzzzzzzzzzzzzzzzzzzzzzzL)+)Y " + "b.-=jf{-216,}${/!}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}|]", + 2, 0 }, + { "[^\\\\\\\\\\(\?<=\\\\\\\\\\\\\\\\m]{-48,234}[:alpha:]s)", 0, + 0 }, + { "[(\?{U}(\?<!)])LLLLLLLLLLLLLLsssssssssssssssssssssssssss[:" + "ascii:][:blankcntrl:]---------b", + 0, 0 }, + { "[^[^[(\?#)(\?imsxims[x:)<<<<[<<<<<<<<<<(\?<!<<<<<<<([^\?(<<<" + "<<<<<<<z(\?(zu(\?<=~83}aZpIE)[:alnum:](\?imsximsx:(\?!jrE6(" + "\?<!\?V(SzDU)000[000000000((\?=\?)=0])L|lOYuWXk", + 0, 0 }, + { "$o[:dig(it:]nnnnnnnnnnnnnnn{-94}|G)[:alpha(\?!:] " + "{,-108}D=\?>[:digit:]S[:space:]t", + 0, 0 }, + { "()n", 1, 0 }, + { "[:upp(erword:]$)<}.vZM<lEY5Y*", 0, 0 }, + { "[^([^\?>)rCD&{5(\?msxisx:7,}qqqqqqqqqqqqqqqqqq{31,}@w#W:(@(" + "\?:zp$YYYYA[:alpha:]{1}A)*dZJ\"5OG|\?(\?#a])]|){-150}[:" + "xdigit:]", + 0, 0 }, + { "[($)gwo{`\"]{-160,}" + "\\\\\\\\\\\\\\\\\\\\\\\\\\66666666666666888888888888", + -1, 1 }, + { "((}DA+Rc000000000000000000)%vvvvvvvvvvvvvvvvvvvvv%C&emZ*[:" + "alnum:]#m/" + "D[:graph:][:blank[^cntrl:]E{,168})" + "kkkkkkkkkk000000000000000]", + 2, 0 }, + { "[^[u*(\?#x01234)oxGGGGG(\?([GGGG)GGGGGGGGG]^U)!!CCCCBM`4QB^" + "XEN]{,-60}[:upperword:]G]", + 0, 0 }, + { "(%)~t{S,K^MI3PMo)=b", 1, 0 }, + { "[[[^]{}eU([:xdigit:]&&&&&&&&&&&&&&&&&)\"W|43[:alpha:][:" + "graph:]J8b[:blankcntrl:]gggggQ{,183}{,-254}\?[:ascii(:]{," + "134}", + 1, 0 }, + { "[[([^[^([^(\?=)1RRRRRRRRRRRRRRRRRRRRRR(\?:(\?(\?(\?!=#RRRRR(" + "\?=RRRR(\?<[^!Ru)])]o[:[graph:[^]{,7})[:digit(\?::]{-215,}e[" + ":space:]]", + 0, 0 }, + { "({{{{{{{{{{{{{{{{{{KKKKKKKKKKKKKKKKKKKKKKKKKKKKBBBBBBBBBBBB)" + "[:space:]0[:alnum:]HcctQA", + 1, 0 }, + { "[^(pP7(HsN[^g{186,-87}\?\?]EQ%u:-Y)+>>>>>>>>>>>>>>>>>>>>>pP]" + "[:alpha:]", + 0, 0 }, + { "[(.{141}h|)((\?:\?=@Q} " + "ghcC{+*(R)D+][:lo(\?#werprint:]" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz))", + 0, 0 }, + { "[^({}S)PPFl(])-216", 0, 0 }, + { "[([[^(((([(\?#^[^[^\?4[(:[dig[^it(\?(:]{122,})y\?", 0, 0 }, + { "[[2${188}u{1(4(\?(1,1(\?{98}e{&tbaoI]q)[:punct:])d}))" + "Nqffffffffffffffffffffffffffff[:ascii:]+]", + 0, 0 }, + { "()K-", 1, 0 }, + { "[[{2(2((\?(\?!()2})])[:alpha:]fVVVVVVVVV{-47}):::::::::::)" + "\?vwyyyyyyyyyyyyyyyyyyyyyyyyy-]{}", + 0, 0 }, + { "ivcs)g", 0, 0 }, + { "(hhhh[^hhhh(\?{h\?]})%%%%%%%%%%%%%%%)\"+38mbY:s9{/d# " + "zaNnbQb)b:*zpKI{-26,-189}", + 1, 0 }, + { "S*(#)[:graph:]lllllllll&G)t", 1, 0 }, + { "([^[(([\?=\?<!)]]___{-63,})]nt", 1, 0 }, + { "[:b(lankcntrl:][:alpha:]*[:pu[^[nct:][:alpha:]A]$" + "aaaaaaaaaaaa*)A[:digit:]U][:alnum:]", + 0, 0 }, + { "[^f[^p000{68(\?isxmx:,}(\?!vvvvvv)$)]PP#*{(})[:punct:]&&&&&&" + "&&&&&&&[:punct:]\?][:blankcntrl:]", + 1, 0 }, + { "[^(((\?(\?(()))GGGGGGGGG{(\?!($)))((\?!)V^{228,145}))]{-229}" + "Qjjjjj[:punct:]R)", + 0, 0 }, + { "[(Q[^((\?{(\?:]~z)})gE(.<){}|)Kuuuuu$*" + "222222222222222222222D]", + -1, 0 }, + { "([^`(\?<=`````[^`````````M]\?)=L74A[:upperword:]]P", 1, 0 }, + { "(({}[:space:]qv-T){,-192}{-45}{65}9\?X).d", 2, 0 }, + { "_[(:upperword:]mU(P}qX>\?%)$Lwq[:alpha:]{-115,}=============" + "==================={127,}", + 1, 0 }, + { "e)", 0, 0 }, + { "[{,2[5}Klen+D0'YX(\?<=|_H]I,Y\"*/<3sM[:digit:]])#.", 0, 0 }, + { "[:(xdigit:]){[:digit(\?mxmsx::][:as(\?<=cii:]d!{135})#)pP[:" + "space:]Syyyyyyyyyyyyyyyyyyyy\"Gg8", + 0, 0 }, + { "[(\?()])", 0, 0 }, + { "[^([^[^[[^[:alpha:]SIus[^f<f]}}}}}}}}}}][:xdigit(\?=:]Z{-13}" + "*]_[]LLLL)]E[:alnum:]b$)]]]]]]]]]]]]]]]]]]]]]]]]][:" + "lowerprint:][:ascii:]{,40}{86,}" + "333333333999999999999999999999999999*" + "fffffffffffffffffffffffff99999999U9|[:digit:][:upperword:]" + "oowwwwwwww[wwwwwwwwww{195}[:xdigit:]]H{-73,153}R+zAz{}r/////" + "////////" + "{232,}kAoffffffffff[:blankcntrl:]xxxxxxxxxxxxxxx]KKKKKl0,[:" + "alpha:]|{,-165}Qc{96}CCCCCCCCCCCCCCCCCCCC/", + 0, 0 }, + { "{}:V(7O-)[:ascii:][:graph:]PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#", + 1, 0 }, + { "[^(\?<[^=CC(CC$)]* c)BBBBBBBBBBBBBBBBBBBBBBB]z{-18,}", + 0, 0 }, + { "[[qqqqqqqqqqq(\?(qq235|ttttttttttttttttttttttttttttt[[ttt<<<" + "<(\?{<<<<<<<<<<<<)<<<<<<<<p)/" + "S9(\?{OOOOOOO(\?<!OOOk)})]nIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIb]" + "Z})", + 0, 0 }, + { "[^[^(\?>][^((\?<!C(\?!+(\?=)]^8)6nx).)){,-13}[:blankcntrl:]" + "\"(L{}){,29}nnnnn{-83}]l[:upperword:])", + 1, 0 }, + { "[(ZZ\"#(\?#Nb(\?<!:U)oRRRR])Zei${Ec/)s", 0, 0 }, + { "[^[^[(\?(t(\?:3```````)`````)|#CB)//////////////////////////" + "///" + "*!liB#|CCCCCCCCCCCCCC(\?=CCCCCCa7N]weTTTTTTTTTTTTTTTT1{}o\?{" + "}BBBBBBBBBBBBBBBBBBBBBBBB.])u{-218,126}.,[:space:]]", + 0, 0 }, + { "[[([:alnum:])yyy(\?!yyyyyyyyyy(\?!yyyyyyyyyyyyyyyyyyy[:" + "graph:]I])Uw*X.^[:ascii:]{,-63}[:digit:]{-88})&&&&&&&&&&&&&&" + "]*", + 0, 0 }, + { "[[[^K(\?=KKKKKKKKKKKK(\?:KKKKKKKKK[KKKKKK]]U[:digit:])]dd)({" + ",16})xy+Pu)JJJJJJJJJJJJJJJ[:space:][:ascii:][:upperword:]ql_" + "jywmt4B+]{-30,}^555555555Xza[:punct:]", + 1, 0 }, + { "[[^^XXX(\?:XXX((XXXXXXXXXXXXXXXXXXXX)v)$N9$" + "r\"\"\"\"\"\"\"\"\"\"\"\"\"].{,239}$[:punct:]\"9999][:alpha:" + "]{}c){,55}s[:upperword:][:xdigit:]310", + 0, 0 }, + { "[@([^I8oNl)]-{-203,-224}{-78,}KKKKKKKKc{-66}[:xdi(\?=git:]==" + "========){}f{-124,}[:upperword:][:lowerprint:]]{}--------l+", + 0, 0 }, + { "[^]ozp+0(\?#\"[(\?()X]))[:blankcntrl:][^e{99,222}" + "JJJJJJJJJJJJJJJ3F]\?[:blankcntrl:]l$ot", + 0, 0 }, + { "[[^[[((\?isximx:)2222222222(\?=22222[:graph:])+U)((\?{\?<=(" + "\?()iYv8qc@#y)G])+}))FvnP\"7OZ-b273[:ascii:]Ak6*`S[:digit:][" + ":graph:]]{2}^G{79,}DDDDDbbbbbbbbbbbbbbbbbbbbbbbb(bbbbbbb)|" + "tP48y{wNJ_S hJbY]]dc", + 1, 0 }, + { "[:alph(\?{a:]p1[:lowerprint:]}){163,}", 0, 0 }, + { "W()", 1, 0 }, + { "()``````````````````````````[:ascii:][:alnum:]{,26}[:graph:" + "]", + 1, 0 }, + { "[:al(\?<!num:]|byyy,*)U5%u${190}-{-221,-33}" + "k7777777777777777777777777777777+eXXXXXXXXXXXXXXXXX[X(\?(XX)" + "XX)S'vEAa]*e", + -1, 0 }, + { "[^(([R_AC[lE'{2(\?{28(]8LTt[]b[:punct:]]O)|2[:graph:][:" + "space:]}) " + "x3C[:alpha:])uI+dddddddddddddddddddddddd{-165,}" + "FFFFFFFFFFFFFFFFFFFFFFF)cccc*[:upperword:]]G{,-38}{24,}" + "555555555555555555555555555VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVZ[" + ":blankcntrl:][:ascii:]", + 0, 0 }, + { "[^QQQQQQQ(\?#QQ(QQQQQQ[:punct:][:space:]){(\?(\?:!}[:graph:]" + "t}}[^}}(}}}}}444444[^444444444444444444444]\?]G)E)L{,-103}{" + "84,}r$ii]-[:alp(\?<=ha:]S5G~9>n*)P<" + "3tttttttttttttttttttttttttt)n{}[:graph:]" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{,83}[:digit:])" + "0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[:alpha:]{-155,}{151,}", + 0, 0 }, + { "Ue{,254}+f[:lowerp(\?<=rint:]U.fff)", 0, 0 }, + { "QQQQQQQQQQQQQQQQQQQQQQQQAY<J)'MPi_u%#2doopqU7/" + "{103}[:graph:]e!7{GOr", + 0, 0 }, + { "[^({,[^233}[^d)BBBBBBBBBBBBBBB=======(\?>===========[^=S|[^[" + ":alpha:]G/]qqqqqqqqq{}[:xdigit:])..k", + 0, 0 }, + { "[([^[[:space:]ffffff(\?=ff]M]))[:xdigit:]UbCI,CzalLU*y5I[:" + "digit:]r{-30,180}{-209,-45}Paf]", + 0, 0 }, + { "[^[h(\?{hhhhhhhhhhhhhhhhhhhhh})]{,143}[:lowerprint:][:ascii:" + "((\?(\?=])[:asc)ii:])zp]", + 0, 0 }, + { "[[(\?{]})]", 0, 0 }, + { "[[1\"3m^,(\?<!2((\?!\?#t```````````````````````````)\?)|c^)" + "A^~]{61}W\\\\\\vvvvrrrrrrrrrrr[:digit(\?#:])]F[:upperword:]" + "dX\\\\", + 0, 0 }, + { "([${144,}(\?<!)-RAk_F(\?imsxisx:=9]z/))", 1, 0 }, + { "[[^[[[^([[^[^[^([[^([[Uiiiii#####(\?(\?{(\?<!#########(\?=##" + "###).^)(.|>2m[M/" + "2222222222222222222222222222(\?:22222222222(\?#22(\?:(\?=" + "22222{,243}]x68+I/" + "K)11111111111]\\pP[:graph:]$[:space:]^{}A)[:xdigit:]-={>", + 0, 0 }, + { "[(\?>[(^()Vty2vvvvvvvvvvvvvvvvz^])ZZZZZZZZZZZZZZZZZZZ-------" + "---------5\\dVLSp8UE2m+z3X/Sd", + 0, 0 }, + { "[}}}}}}}}}}}}}}}}}}}(\?#}}(\?<=)|*C " + "]*29JW7O9mEB]pE_OoxN)[:alpha:]", + 0, 0 }, + { "([^((\?<=\?)D{,200}.[(\?#:ascii:])[:space:].)[:alpha:]D|[:" + "graph:]{,-41}*LLUUUUUUUUUUUUU{-189,-131}]qHR<k2@P{27}<^e,ub%" + "\?/4){-243}+[:digit:]%*x9lA^", + 1, 0 }, + { "([:alpha:]bT&+_)$Z{,212}x26`", 1, 0 }, + { "[^([^(A{[^}g(\?()A9p#54b]-------------------------------)." + "wzD#=f\\)A)8a]]DNNNNNNNNNNNNNNNNNNNNNNNNNN", + 0, 0 }, + { "(W000000000000000000000000000000)", 1, 0 }, + { "www(wwwwwwwwwwwww)", 1, 0 }, + { "()555555555555{18}i+[:alnum:]E {}U", 1, 0 }, + { "SqbHoooooooooooo[^oooooo([^ooooooo])\\N[:xdigit:]]oooo`", 0, + 0 }, + { "[999999999999999999uE{193,0}lx{7917}[:punct:]4&d]{221,}[:" + "digit:]{49,156}[:lowe(\?<=rprint:])[:space:]{-33}w+", + 0, 0 }, + { "[^(\?{})<{220,-193}[(\?=:xdigit:]UUUUUUUUUUUUUUUUUUU'{-18}]" + ")", + 0, 0 }, + { "b[(\?<=:upperw(\?{ord:][:digit:]})EEEEEEEEEEEEEEEEEEEEE/////" + "/////////////){177}C", + 0, 0 }, + { "(^).[:alnum:][^[(\?=[(\?{[})DA5{)[[I~y&O\?9>])]][:" + "blankcntrl:]M[:alpha:]x9[:upperword:]|[:xdigit:]b", + 1, 0 }, + { "()[:digit:][^[U}-]]{,206}V*WJ@R]\?", 1, 0 }, + { "[^](\?#{}(\?[<=)yv)]r", 0, 0 }, + { "({,-192}//////////////////////7!eW_0eoL){}", 1, 0 }, + { "^[:punct:(]+)IIIIIIIII[:punct:]P$pP", 0, 0 }, + { "[(\?=|U)^-]{-52,-72}[:digit:]*6666666666\?{{{", 0, 0 }, + { "([^f(\?:+{1((\?=34,}]))^)s0bux7\?5`Bwr[:upperword:])Dy+", 1, + 0 }, + { "AL{}:::::::::::::::::::::::::::::::{,(104}~@,Ysey@h).", 1, + 0 }, + { "[^((.)))(\?()))))))))))))))))))))(\?msxims:))))))))))[)][:" + "upperword:][:alpha:])", + 0, 0 }, + { "[^(()f])G^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^T{}N*nK[G]{,61}^^^^^" + "^^^]", + 0, 0 }, + { "[(N::(\?<=[:digit:][:graph:][:space:]xB5[(:xdigit:]|Yv{}" + "HHHHHHHHHHHHHHHHHHHHHHHHd).[:g(\?<=raph:])[:digit:]<<)[:" + "digit:])[:space:]Q[:punct:]x7C]", + 0, 0 }, + { "[^((\?(\?(())a)(\?!){})W)pP3333333333(" + "33333333333333333333hhh]{})", + 0, 0 }, + { "[^ [ " + "a*FFFFF[^FFFFFFFFFFF(\?<[^!FFFF(\?=FF])])L1]{,-52}{B-bxsPKg{" + ",8}[:digit:][:punct:][:upperword:]DD${,-131}", + 0, 0 }, + { "($$$$$$$$$$$$$$$$$$$$$$$$$$$$$^pP),,,,,,,,,,,,,(,,,,,,,,,,,," + ")QQQQQQQQQQQQQQQQQQQQQQQQ", + 2, 0 }, + { "[:lowerprint:]|l{(,-54}C{}*-)IIIIIIIIIIIIIIIII", 1, 0 }, + { "()+", 1, 0 }, + { "[(([(\?{[:punct:]]|))[[[[[[[[[[})]WWWWWWWW&$$$$$$$[:graph:]", + 0, 0 }, + { "[^(\?{}){(107[(^,}][:space:[]))^w,&aPPPPPP[^PPPPP{117,-213}" + "s\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?]]]222222[:d(\?(" + "igit:]NNNNNN)NNNNNNNNNNNNN8)I", + 0, 0 }, + { "[^(\?<!$)|TTTTTTTTTTTTTTTTTTTTTT(TTTT]a8)2<", 0, 0 }, + { "([^[]%[^[^]-][:alpha:]37*:[:space:]]lQvu)[:xdigit:][:" + "blankcntrl:]", + 1, 0 }, + { "[[Bl_>9C^:\?X_KK]2sw@hHZT!],uuuuuuut|lFW()''''''''''''''''''" + "'''[:graph:]<~v{-251}0[:digit:]C[{222,}]{,41}{}*g^UuS/" + "{-114}", + 1, 0 }, + { "(D{,-79}[:gra(ph:(\?(]C[:ascii:]))I[tC.%tkllll[^" + "llllllllllllllll]&&&&&&)&&&&&&&&&&&&&&&&&&&&&&)]10435", + 1, 0 }, + { "[:al(\?{[^num:]]})}x'[:(\?#xdigit:])" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKKKKKKKKKKKKKKKKKKKKKKKKKKKKTT" + "Tr*%{~f", + 0, 0 }, + { "[ZQKEEEEEEEEEEEEEEEEE(\?<!]3|.~~~~~~~~~~~~~~303)" + "33333333333333333", + 0, 0 }, + { "(-62([:ascii:]5555){-230,}<<<<<<SM[:punct:]{72}|E{160,})" + "Pfqba!{,-188}DS{ +2tRu\"0JG$", + 2, 0 }, + { "([^(\?:(Ea00000000000000[:punct:][:graph:]{}]))[:xdigit:]{-" + "65}t){164,}", + 1, 0 }, + { "[\?$$$$$$$$$$$$$$$$$$$$$$$$$F......(\?(.).q#R:j6%TTLCdtuM|8*" + "54<GHoqEh9FBW0:W]L0)o][:upperword:]", + 0, 0 }, + { "[(\?>[:alnum:]W[:space:]]D)|L", 0, 0 }, + { "(M(MM)[:alnum:]|[:lowerprint:]4)", 2, 0 }, + { "[[^(\?:{}{2[2(\?>0,})]]]Etu)-)", 0, 0 }, + { "([^[^^z[:graph:]]#{-144,96}[:punct:]!4LY//////////////////" + "SSSSSSSSSSSSSSSSSSSSSSSSS[[^:xdigit:]\?`-!L#p0{52}]%{-121,}[" + ":graph:]]WqJ>$6UBg{,7}[:blankcntrl:])[:upperword:]y2wW!A[:" + "blankcntrl:]0CN\?", + 1, 0 }, + { "[[^(\?:|+bII(IIIIIII(\?(\?>!)275SIIIIIIIIII(IIIIIII(\?=" + "IIIIII[:graph:]|)`]S\?.}A)[:alnum:]Jgggggggggg{-150,}{-89,})" + "[:alpha:]Q)|07be5:j)]", + 0, 0 }, + { "([(\?i(ms(\?=x-x(\?>:))C)]){})>eIqm~lFb[:upperword:][:" + "blankcntrl:]w=[:digit:][:graph:]", + 1, 0 }, + { "([HHHHHHHHHHHHHHHHHHHHHHHHHH[^HHH(" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?!!!!!!!!!!!!!!!!!!" + "!!{23}]~J=[:ascii:]tttttttttttttttt])-216", + 1, 0 }, + { "B{[^-32,246}{13(\?!0}q>GVQw*[:digit:][:punct:]." + "77777777777777777777`T(-t01odD]\?${}{-247}+gV{131})+[:" + "lowerprint:]m/z~d", + 0, 0 }, + { "[t[$FV+(\?=E=[^])]-$U{-22[5,}{253,}08g]$[{}][:xdigit:][:" + "punct:]{-18}{-173,}]{,-191}V_|90", + 0, 0 }, + { "()$", 1, 0 }, + { "[^[^((((((((((((((W[(\?::blankcntrl:]&-JH]J){93}LLLLLLL|r{," + "221}tY/172]-AS", + 0, 0 }, + { "[^()(\?{qqqq(\?msimsx:qqqqqqqqqq3999999999999GGGGG|S*W%{," + "128}][:xdigit:]AJt]}\"Zf!lRpr{>){,36}})", + 0, 0 }, + { "[([]^]^)", 0, 0 }, + { "([.(\?#){}[:alpha:]\?S{2}P%Gw]" + "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnYiq5)>i*r<", + 1, 0 }, + { "[ggggggggggg$PPP:S " + "(:]N{239,}|A[:lowerprint:]vvvvvvvvvv[:lower(print:]{-184}({-" + "133,}+)[:punct:]P/Q.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", + 1, 0 }, + { "(RRRRRRR[^RRRRR[RRRRRRRRR])]", 1, 0 }, + { "[(\?:^])D%", 0, 0 }, + { "()[]#C[+[j]{,29}-]", 1, 0 }, + { "(([(\?(((\?{\?!(\?=\?=#[Es*){02$r'}(\?:3pz)" + "uPPPPPPPPPPPPPPPP(\?(\?>:PPPP][:graph:][:ascii:]`.)[:punct:]" + "[:a(\?mxi:lnum:])r)$)[:xdigit:]$[:(\?=digit:])aa[^]a)\?])" + "sQQQQQQQQQQQQQQQQQQQQQQQQQQ^|$)-}))", + 2, 0 }, + { "z@@@@@@@y${}[:(\?:upperword:]l\?{,144}-)", 0, 0 }, + { "[:aln(\?:(\?>um:(\?imximsx:]){})FGGGGGGGGGG|-p){,105}", 0, + 0 }, + { "[[{17}llllllllllllllll(\?:lllllllll{,(\?#-94}OUUUUUUU(\?#" + "UUUUUUUUUUUUUAA]p[:digit:]{-1(57,}5yyyyyyyyyyyyyyyyyyyyy[:" + "alnum:]v{-185}^^^^^^^^^^^^^)d[[[p)]))", + 1, 0 }, + { "()|[:digit:].E2o", 1, 0 }, + { "()3[:lowerprint:]", 1, 0 }, + { "[(\?{(\?#(\?>SN}[^)z+r^t[:digit:]seP[:alnum:]$b1ZY[U(\?<!" + "U4IIIIIIIIIIIII(\?<=IIIIIIIIII]m)]))]4)", + 0, 0 }, + { "{,74} qkk[^p]kbi6>{}000000000000000000000000000000$|)", + 0, 0 }, + { "[:(\?=digit:])v{164}", 0, 0 }, + { "[:graph:]h[:upper(\?(wo(\?{rd:)])00000[^000000000000})." + "4OEVf{,-46}]A", + 0, 0 }, + { "[](((((((((((((((N{{{{{{{{{{{{{{{{,-1}e]a{-166,-44}", 0, 0 }, + { "([[^[^[(^[]]YYYYYYYYYYY]D.cQ{}[:alpha:]ttttttt000000[^0000(" + "\?<!0000000000000000N::::::::].][:alpha:]#5\?{}{-253,-193}]" + "\\[:ascii:]tS{,35}B)ffffffffffffffffffffffff))/", + 1, 0 }, + { "(G)[:alpha:(\?#])W{-197,-220}w8", 1, 0 }, + { "{-2[^00,(\?#-([84}ig+)]]l[:graph:][:graph:][:space:])" + "aaaaaaaaaaaaaaaaaaa{-208,}ea{,224}", + 0, 0 }, + { "[^[W(\?<=[B[:xdigit:]{255,}FAAAAAAAAAAAAAAAAAAAPP])[:xdigit:" + "]+][:lowerprint:]${-195}", + 0, 0 }, + { "[v{104,}BB].HHHHHHHHHHHH[:ascii:]" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbb(btttttttttttttttttttttttttt){" + "180}", + 1, 0 }, + { "[^(i[^iiiiiiiiiiiiiiiiii(ii)n])#######################]", 0, + 0 }, + { "(([:space:])[:g(\?>raph:])[:punct:][:upperword:]LV\"t+t!)[:" + "ascii:][:lowerprint:]q", + 2, 0 }, + { "[[[^([7(\?[<!)\\PP~D7L (\?imsimsx:(\?= " + "$GS26L3-J(\?()!)]]{-178}%$[:p(\?!unct:]))yyyyyyyyyyyyyy@w,[" + "11!R86:)G*[(\?(:blankcntrl:]267$~L\?{-108}k[:alnum:]So\?Y/" + "eq]-|[:xdigit:]555555555555555555555555555)55555........W*O)" + ")][:alnum:]]I{,-126}[:lowerprint:]8\?[:xdigit:]u%wHc6\?:Pc.." + ".........................,,,,,,,,,,,,,,,,,,,,,,,,,,,]", + 0, 0 }, + { "((3pPp))QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ", 2, 0 }, + { "[[^]{-244[}(\?([^|W0E4]UUUUUUUUUUUUUU[:upper)word:][:space:]" + "{-57,})+L>R]]$PeFuufcBA`qr!!!!!!!!!!!!!!!!!!!!!!!!!", + 0, 0 }, + { "[[(\?#F^(\?<!)|)fff(\?!fffffffffffffffff(\?{ffffff(\?:" + "ffffff[:alnum:])]]c.\?-}))", + 0, 0 }, + { "[^[^((\?:)ww[wwww(\?>wwwww)3z/57z){34}]/(/////////////[^////" + "//////////////)]E%)L{-133}]*$]", + 1, 0 }, + { "(!)GS[:ascii:][:punct:]{235}T'&-_h\"", 1, 0 }, + { "(){}", 1, 0 }, + { "[[^((\?!(\?<=)*QF[:alpha:])([^[^\?<!x60t(\?<!" + "UUUUUUUUUUUUUUUUUUUU)K&d{118}z7nM.G)````````````````````````" + "```E:(\?(){31,}){}]k]){,109}[:space:]]ZZ[:xdigit:]]{-68,}`{}" + "{}e\?[:alnum:]", + 0, 0 }, + { "[^{223}.^,-qqqqqqqqq((\?!\?>qqqqqqqqqqqqqqqqqqqqqqqP6W0_'O)" + "Bur*'6&*t)]{65})+", + 0, 0 }, + { "([(\?=)]wr$7f5ru){100,}[:xdigit:]y{}[:digit:]{}2n@P|9#mru~" + "97{-189,73}$a", + 1, 0 }, + { "({-113,213}){-172,221}B[:ascii:]{,-48}", 1, 0 }, + { "[^[[Xf`````((\?{(\?<=\?imsmsx:`````````(\?!`````````[```(" + "\?mximsx:``(\?(&|o{xIaO][:)space:]3))\?])+)*<|@@@@@@@@@@@@@@" + "@@@@@@@@){-251,}{}]*[:graph:]1!azE\?|-120u*][:lowerprint:]}" + ")", + 0, 0 }, + { "[[[^##(\?################(\?>(\?(##t)][:punct:])b))<<<<<<<<<" + "<<<<<<<<<<<<<<<<<[:alnum:]y " + ">u=l:rp8i3Ci#]46%NIO-W[:space:]IIIIIIIIIIIIIIIIII]W[:space:]" + "f]l{-253}", + 0, 0 }, + { "[:graph:]L{-136,175}{[^}h(\?=t)Q]ooooooooo(" + "ooooooooooooooooo_)[:space:]q\?", + 1, 0 }, + { "()$.", 1, 0 }, + { "[(\?<!^$.\?{197}B]$)", 0, 0 }, + { "[:di(git:])[:low(erprint:])qqqqqqqqqqqqqqqq[:digit:]", 0, + 0 }, + { "((zzzzzzzzzzzzAUUUU)l$]VD z~)n", 2, 0 }, + { "([^[(\?<=^[]{}][.WWWW)044444444444(\?=44(\?{444(\?{(" + "444444444444e{(\?=}}))..t]+[:(\?<!xdigit:]P]-N}))))|)", + 1, 0 }, + { "\\ce[:(\?#asc(\?{ii:])})[:upperword:]`^", 0, 0 }, + { "[:graph:(\?<=])[:alpha:]", 0, 0 }, + { "([:upp(\?=erword:])pC)lp\?", 1, 0 }, + { "(oooooooooooooo\?fN)-[:alpha:]{-213}[:alnum:]qHEu", 1, 0 }, + { "[:punct:]TTTTTTTTTTTTTTTTTTT[:d(\?#igit:])[:alpha:]", 0, 0 }, + { "([^[^[^J4(+++++++++++++++++++++SgDE(\?>\"y8].]::::::::::::::" + ":)pP5-]p)O{,199}xxxxxxxxxxxxxxxxxxxxxx[:ascii:]%", + 1, 0 }, + { "([:alpha:]Fs)Z", 1, 0 }, + { "[()]{209}[:alpha:]hhhhhhhhh(hhhhhhhhhhhhhhhhhhhhh)pP<<<<<<<<" + "<<<<<<<<<<<<<<<<<<<<<", + 1, 0 }, + { "-{-8,}.[:(\?imsxx:ascii(\?<!:]{-231}aa*{}K^UQL\?)d\?[:" + "lowerprint:]W)q>D9'", + 0, 0 }, + { "[#(\?msximsx:#########################-IIIIIIIIIIIIII(IIII(" + "\?#IIIII((\?#[^III{})N.[(\?=:lowerprint:]))CwT,,,,,,,,,,,,,," + ",,,,,,Sq]$CCCCCCCCCCCCCCCCCCCCCCCuuuuuuuu])))", + 0, 0 }, + { "[:xdigit:][(\?#]){13}{,75}lllllllll", 0, 0 }, + { "[c]QQQQQQQQ1+{-252[(\?#}33333])[:upperword:]", 0, 0 }, + { "P@i #>>PF!@8G<[(\?:^P]-)D", 0, 0 }, + { "uZZZZZZZZZZZZZZ[^ZZZZZl*-211{199}(\?!p])" + "EEEEEEEEEEEEEEEEEEEEEEEEEEED[:lowerp(\?msximsx:rint:])", + 0, 0 }, + { "[(\?!^])021[:graph:]'", 0, 0 }, + { "\\(\?>[(\?<=:ascii:]{}[:alpha:]d8}G))", 0, 0 }, + { "[^[((\?!1)[^,a|]\?{,242}[:alnum:])X\"a", 0, 0 }, + { "pP[((\?simx::a(\?!lnum:]vvvvvvvvvvvvvvvvvvvvvvvvv)|O0)[:" + "digit:]ooooooooooooooooooooo)" + "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"", + 0, 0 }, + { "_ L:8J-~ Y$[:uppe(rword:]{,-184}]{}6.A)", 0, 0 }, + { "{,105}.(9]]{-12})N@0nOOE", 1, 0 }, + { "HHHHHHHHHH[:xdigit:]uuuuuuuuuuuu{}E^X\\\\\\12601", -1, 1 }, + { "( o)=\"OU7h{V>", 1, 0 }, + { "[[:xdigit:])))))$[:xdigit:]+{152}{,-50}(c),,,,,,!!!!!!!!!!!!" + "!!(\?>!!!!!!!!!!!!!.[:digit:]i>\"O'i9])-175d_", + 0, 0 }, + { "[([^[^[^([[Eeee[^eeeeeee(\?(\?<!(eeeeeeeeeeeeeeeeeef|]][:" + "alph()\?>(\?!(\?>a:]a{,166})/////////////////////" + "[:gr[^aph:])Gpu", + 0, 0 }, + { "(7)NNNNNNNNNNN132", 1, 0 }, + { "[([\?#^[]{QKm$v])][:alp[^ha:]]", 0, 0 }, + { "(:{86})7{K|[:alpha:]{O", 1, 0 }, + { "([Y(\?{[[^:alnum:][:alnum:][:digit:][:a(\?(lpha(\?(:].})", 1, + 0 }, + { "[[({29,-30}([[^:digit:])Y]]J=~{,220}[:blankcntrl:])" + "0ooooooooooooooooooooooooooooooo[:punct:]&]", + 0, 0 }, + { "[^1Dx32[:alnum:]]{[(\?::punct:]MMMMMMMMMM)12759", 0, 0 }, + { "([[[]]*|(_])[:u(\?{pperword:]})", 2, 0 }, + { "[:upper(\?(wo)rd:]){-16,250}", 0, 0 }, + { "([^{194}i(\?({161)}PP\\S{}{,-14}]))z{208,225}BpPEt", 1, 0 }, + { "[(\?m-ms:)}&!@29k0sUqzt9}<-x|A$!+G>>>>>>>>>>>>>>>>>>>>>>>>>>" + ">>>>>>CCCCCCCCCC-][[:space:]][:space:]El", + 0, 0 }, + { "()[:digit:(\?isx(\?>ix:]K^WQQQQQQQQQQQQQQs)[:lowerprint:])", + 1, 0 }, + { "[a|(\?imix:S(\?(SSSS)SS(\?>S)]W)8t[:ascii:]f$)[:alnum:]" + "111111111111111111111[^[:space:]x{12729}+'''''''''''''''']", + 0, 0 }, + { "[^(\?!(\?(\?#=)a)[:punct:]=2)(){}$$$$$$$$$(\?ims(\?#-isx:$$$" + "$$$$$$$$$$$$$(\?#$$s)x{294b}##############################" + "slllll)]){,209}333333333333333333G:v2/K", + 0, 0 }, + { "[^]ub(\?<=)vQ6(\?#Z\"3.)[:space:]u[[:digit:]]" + "7777777777777777U'{}sssssssssss", + 0, 0 }, + { "(([(])`[:ascii:]b)", 2, 0 }, + { "[[[^[^([^[^(\?=(\?imxisx:[[^w])", 0, 0 }, + { "pppp(pppppppppp-{-175}Nb>k&)sssss{-190,-54}", 1, 0 }, + { "()OJ@`'%[:(as(\?!cii(\?#:]))+pffffffffffffffffffffffffffff{," + "162}[:ascii:]5)s-[:graph:]", + 1, 0 }, + { "[(M{}Ux5{jaW/" + "{}[^u[:alpha:]s^{84,}PPb@Wt$(\?>nha<Yf41a)]{}[:lowerprint:])" + "*[:lowerprint:]][:upperword:]^1gS.^=pp{}" + "FFFFFFFFFFFFFFFFFFFFFFFFFFF33333333333{}", + 0, 0 }, + { ")\?L9~h4BQnNp F\\Q{}", 0, 0 }, + { "($)[:upperwor(\?:d:])N[:alnum:]" + "bcccccccc5555555555555555555555555.N[:blankcntrl:]", + 1, 0 }, + { "2222222222222222222ppppppppppppppppp[:lowerprint:]))[^B\\e{{" + "{{{f]6#+{,-104}{{{{{{{{{{{{{", + 0, 0 }, + { "<[(\?>:al[^pha:]])\"O\"vN", 0, 0 }, + { "[(\?>d8E@b.{(\?<=,-250}(\?=mx48[:punct:]^&)]nAeYY)W)-13272", + 0, 0 }, + { "22222222222222222222222222///////////////////" + "[:digi(\?#t:]eM)[:lowerprint:][:alpha:][:alpha:]EEEEEEEEEEE", + 0, 0 }, + { "[(\?={38,223})^\\\\\\\\\\\\\\\\L(\?:{,-50}3|)}r]aW\\x70U{-" + "110,}8LUf)w]4+oav", + 0, 0 }, + { "G[:upperword:]v[:lowerprint:]-tu)j8CK", 0, 0 }, + { "[([([^().(\?(\?><=c)'(\?<(='(\?<!''''''''(\?(\?<!!''''''''''" + "'(\?=''''''/" + "(|dHj(P>L\?q!G))|)(\?=n(\?(^tk)T-z$q!D|2<rc[^{,53})]jZy))))" + "6)[:bla)nkcntrl:])010])7pE`l[:space:]([:lowerprint:]" + "eXXXXXXXXXXXXXXXXXXXTTTrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr]+[:" + "alph(\?!a:]7)444444444444444444444444l{34,}]J{}" + "yyyyyyyyyyyyyyyyyyyyyyyyyyy)\?'z9~9s.mA", + 1, 0 }, + { "().", 1, 0 }, + { "{-205(,}[:al(ph(\?>[^a:]W,[4DLR[^^8THMtVv~KKw(\?>)pPF)].{-" + "245,}]))fffffffffd[:alpha:]zzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + 1, 0 }, + { "[^[[^]{-[1(\?imximx:83,}{,182}][:graph:]]^])-bTO X0P", 0, + 0 }, + { "[11111111111(\?#11111111]U[:asc([\?!ii:]{,37}+{-89}){-170," + "218}{-21,})f[:xdigit:]]P.[:xdig(\?:it:]145)YYYYYY$S@:@@@@@@@" + "@@{-150,-109}", + 0, 0 }, + { "{-40}<o][^D[(:graph:]]d).Q", 0, 0 }, + { "()APPLn[:xdigit:]", 1, 0 }, + { "[([^\?+++++++++++ [ (\?> (\?( (\?{ " + "(\?!]E{-29})pP)})ZpP", + 0, 0 }, + { "(t|{}c[^z^\?(@YLD]bSSSSSSSSSSSSSSS)+{{{{{{{{{{{{{{{[:xdigit:" + "]n>1)WkF}7", + 1, 0 }, + { "W22[0Q[^d-d{}PPPPPPPPPPPPPPP<^FZ(\?<=\"[U]Yo}9H'cYy]S[:" + "alnum:]^8wTDH)^u", + 0, 0 }, + { "([^[(\?:(\?>((\?#$)(\?{^(\?>))///////////(\?>/" + "ggggggggggggggggg{1(\?!90,-13}\\D)Dyyyyyyyyyyyy(\?!y(\?<!" + "yyyyyyy)})]]$)[:xdigit:]|{}-)#a))nPpP[:lowerprint:]AA)V+q^[:" + "blankcntrl:]", + 1, 0 }, + { "([^(\?!]))D{,97}", 1, 0 }, + { "(c){,141}", 1, 0 }, + { "nn[:s(\?<=pace:])[:upperword:]ooooooooooooooooooo*^[:space:]" + "`{-188,129}mmmmmmmmmmmmm^.", + 0, 0 }, + { "[[G{(\?imsximsx:2(49}{,-46}r(\?(\?=#Gw]u))[:bl(\?>ankcntrl:]" + "))(^m+)zSiZ " + "F4[!]VV$E{-9,-100}''''('''''''''\?DEOOOOOOOOOOOO############" + "###[:space:])HHHH)[:digit:]'////////////", + 2, 0 }, + { "[^*}(\?>)(\?:7Q=#+]KKKKKKKKKKKKKKKKKKKKKKKKKKKG)]]]]]]]]]]]]" + "]]]]]]]]]]]]]][:alpha:]-{}", + 0, 0 }, + { "[n(\?<(\?#!nnnnnn55555{205,}!)[:alnum:]^]!!!!!!!!!!!!!!!!!!!" + "!!!![:punct:])[:x(\?(digit:]vr)|'n6W5 D&jk[:punct:]5)", + 0, 0 }, + { "[^P(P{(\?i(msxisx:235,}))***])[:alpha:]^", 0, 0 }, + { "[([t(\?<!(\?<!4])[:u(\?=pperword:]))-])}}}}}}}}}}}}}}}}}c{-" + "39,}[:digit:]$-", + 0, 0 }, + { "([^)]{241}[:xdigit:][:upp(\?=erwo(\?(rd:]-xF5b{})q[:ascii:])" + "T4U{185}9999999999)()X&Ny[:alpha:]@@@@@@@@@@@@@@@@@@@@@@@@@@" + "@@@@@@{69,}[:alnum:]x{d7f8}p-[:digit:]", + 2, 0 }, + { "(f)(${,111}{25,}!\\d{,94}[:blankcntrl:]@[:space:][:ascii:])-" + "237{,232}DQVVVVVVVVVVVVVV)-", + 2, 0 }, + { "PP[:g(\?!raph:]){}", 0, 0 }, + { "([[^-][^4[:digit:]NNNNNNNNNNN]TVU:])[:ascii:]", 1, 0 }, + { "(([^(\?[[^<=)][:graph:]+iiiiiiiiiiiiiiiiiiiiiiiiii0INFX[:" + "xdigi(\?(t:][:blankcntrl:]][:graph:]qM6A[:alpha:][:graph:])" + "1*]eFvvvvvvvvvv)v-)U))t{89}", + 2, 0 }, + { "[^ZZZZZZZZZZZZZZZiiiiiiiiiiiii(iiiiiiiiiiiiiii{}))))))))))))" + "))))))]))))))))))))))))))))))))[:digit:]-", + 0, 0 }, + { "ddddddddd+zzzzzzzzzzzz[:graph(:])ssssssM{-223}[:graph:]", 0, + 0 }, + { "[:alph(\?>a:])x11{-144,45}.", 0, 0 }, + { "[]{#y.^(\?{{}&&&&(\?:[^&&&&&&&&)[:punct:]n{190}OylBQ{(\?!-" + "73})2u',x(\?#Ds(\?#{})j(\?{-})})u0(((((((\?{(((([:alnum:])" + "MC})b=71TncyE>[:xdigit:]*\\f]{}]\"p#!8twZT\")[:punct:][:" + "space:]", + 0, 0 }, + { "[^(Z6]8)|'@p8{}[:upperword:]MMMMMMMMMMMMMMMMMMMMMMMMMMMM{}" + "7c", + 0, 0 }, + { "$0)@#vp,VcJ.Bdh", 0, 0 }, + { "[[^(-])nnnn+s`[:alpha:][:blankcnt[^rl:][:upperword:]{-15,}][" + ":g(raph:]c]){,-177}6[:upperword:]##################{,-14}", + 0, 0 }, + { "[[(5C{86(,}PPrrrrrrrrrrrrrrrrrrrrr{150,182})N{}LSC|)-[:" + "alnum:]{}KKKKKKKKKKKKKKKK<4=~7K3PPPPPPPPPPPPPPPPPPPPPPP[:" + "lowerprint:]]]", + -1, 0 }, + { "([^(x{145b[5}^hfc.0)+]z@_&lA{-34,}])X\?", 1, 0 }, + { "([(\?<=)(\?!])l)L", 1, 0 }, + { "({-104,}DrPPDF4444444444444[:space:])[:space:]", 1, 0 }, + { "())))", 1, 0 }, + { "[[^((\?>\?(\?[{})q5v}r7t(P)xtffffffffffff))]{,-66}kdExX&-" + "SCeCzzzzzzzzzEc)E,\"^I]x{e629}|{}]", + 0, 0 }, + { "[h[:punct:]p\\[\\\\(\?:\\\\[^\\\\)Eo#:C$u[^T/" + "ysA[*%nM:f]{,221}[:lowerprin[^t:]{]bx{f285}E]E[:alnum:]+]" + "1oe3B][:alp(ha:]]fh7}M$l)D{17}", + 0, 0 }, + { "IIIIIIII[^IIIIIIX]-_S[:digit(\?#:])" + "33333333333333333333333333[:punct:]iiiiiiiiiiiiiiiiii", + 0, 0 }, + { "[^[[:punct:](\?((\?:^ " + "#Q_po(\?=[:alpha:]{}z()(\?!======'wq$Q2)LLLLLLLLLLLLLLLe(" + "C9gggggggggggggggggg[(\?<=:alnum:]()\?<!{-85,}W[[[[[[[[[[[[[" + "[[[(\?{[[[[[[^)(]\?])|uuu[uuuuuuuuuuuuuuuuuu{,-20}p${}]MHI&" + "7s:\?$[:digit:]-:)_V`*{-52,}{250}$:ME9izF/" + "uP[:blankcntrl:]})''''''''''''''''''''''''''''')" + "CCCCCCCCCCCCCCCCCCCCCCCCdd[:ascii:][:lowerprint:]." + "Mcccccccccc2B{-230,}$[:digit:]", + 1, 0 }, + { "()|mOAuK~P144[:space:]^9dddddddddddddddddddddddddddddd[:" + "blankcntrl:]", + 1, 0 }, + { "[^[^[^.L[^-vEUl(\?>(\?=a!Ib1P]])])~~~~~~~]xE9", 0, 0 }, + { "X()", 1, 0 }, + { "[^()(\?#G(\?<!)(\?=^r])*,XXXXXXXXXXXXXXXXX@)444444444", 0, + 0 }, + { "([[((\?<=({,-70})-[:xd(\?=igit:]{,138})", -1, 0 }, + { "[(^]{62,67})", 0, 0 }, + { "([((])[:space:]))", 1, 0 }, + { "(a{(109,})[:alpha:]{,-121}{})]RRRRRRRRRRRRRRRRRRRRRRRR{}{" + "125,}ttttttttt{46,}`[:space:]", + 2, 0 }, + { "[^[^([q[8]~.IPmiBSspP)]QpX[pT==8@lulANS]]{,-98}]", 0, 0 }, + { "[^77777777777777777777777(\?>777777])", 0, 0 }, + { "(),e<^X~{[:alpha:]{}G{70}", 1, 0 }, + { "({-211,}'){}", 1, 0 }, + { "[^(\?imsxsx:{}[*])cccccccccccccccccccccccccccccccc<z0W8]$", + 0, 0 }, + { "(){2,89}$z", 1, 0 }, + { "((050[^\"\"\"\"\"\"\"\"z]8|j{}{,-112}$).pP)qq1~hW}L", 2, 0 }, + { "[[^[(+xx(\?<!xxxxxxxx(\?!xxxxxxxxxx(\?#(\?>[x))(\?:]r.]]]))[" + ":graph(\?<=:])))", + 0, 0 }, + { "[^([(\?#)(\?(\?(<=)l|\?(\?!])kkkkkkkkkkkkkkkkkkkkkkkkkk", 0, + 0 }, + { "[:xdigit:]K(KKKKKKK)^3c.OOO{-240,-10}2{-97,-139}*{-34,}[:" + "xdigit:]", + 1, 0 }, + { "[([^66666666F(\?>FFFFFFFFFFwpP)LLLLLDeDA&Am$l[:xdigit:]!T5#]" + "n[:alpha:]U*)))))))))))))PP]", + 0, 0 }, + { "[[[:punct:]u^[:xdigit:]L(\?:[:xdigit:][[:graph:]PP{21}A[:" + "alpha:]8%I(M%b<eE~#C@r=uG~~~~~~~~~~~~~~~~~~~~~~~~~~~~+w]pP)" + "T]]$$$$$$$$$$$$$$${-121,}|l", + 0, 0 }, + { "([(107{,-4(\?=}~[^D)])f]{,46}+ri<)", 1, 0 }, + { "[(\?<=]{,208}+~)", 0, 0 }, + { "[^444(\?<=4444444[:alnum:]&[,i]0)[:alpha:][:upperword:]", 0, + 0 }, + { "[^([^(\?()*+)SS(\?>SSSSSSSSSSSSSSSSSSSSSS]]]]]]]]]]]]]]]]]]]" + "]]]]]]]]]]]{,-1}])[:blankcntrl:]============================" + "===[:punct:][:blankcntrl:]Z[:space:][:ascii:]$|$[:" + "blankcntrl:] JR.{,133}[:alpha:]$\?)<]", + -1, 0 }, + { "(OL[:u[pperword(:][:s[^pace:].[:spac(e:],,,,]*])$)\?)", 1, + 0 }, + { "(VI[:digit:][:alpha:]6)EG", 1, 0 }, + { "({}){-2,-40}rrrrrrrrrrrrrrrrrrrrrrr[:punct:]", 1, 0 }, + { "()q", 1, 0 }, + { "[^([^[([^C|])]{,-56}[:xdigit:]{-144,}V])fYv{-[40,-58}$@@@@@@" + "@@@@@@@]|Y(-]-.]h-[:dig(it:])>>>dddddddddddddddddddddddddd{" + "101,}", + 1, 0 }, + { "([P,{1(\?(\?(<=28,-218[^)}LoZX)])!!!!!!!!!!!!!!*[:blank(\?!" + "cntrl:]ed)\\\\\\\\\\\\\\\\\\\\[\\L\?][:graph:]:*Y{-108,120}" + "xCC)]", + 1, 0 }, + { "(A[:space:]PP{185}a^!!!!!!lllllll)*db\?$Pfr", 1, 0 }, + { "{-21,-118}kG[(\?{:xdigit:]})[:punct:]{69}" + "Qyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy5{}TTTTTTTTTTTTTTTTTTTTT", + 0, 0 }, + { "[[^[P(\?<=P$X>0^d.[:punct:](\?#ccccccccccccccccccccccccc{}" + "3N000(\?>00000000000000000000000000000]f[:punct:]5)).R======" + "=========={,222}^wwwwwwww$)]-{} " + "]{,-22}CjP{242,}", + 0, 0 }, + { "[(\?#^]{})", 0, 0 }, + { "[^([[([([[([^[^(\?:(\?(\?(!)]\"))h>\"RRRRRRRRRRRRRRRR[^" + "RRRRR{68,-65}7Q(\?{]", + 0, 0 }, + { "(P{}){175,}PP{}rttttttttttt", 1, 0 }, + { "[:bla(\?{nkcntrl(\?#:]})))))))))))))))))))))))!!!!sR{})", 0, + 0 }, + { " [:digit:]dAAAAAAAAAAAAA^[:ascii(:]55)^", 0, 0 }, + { "($*)dZY", -1, 0 }, + { "[:graph:][:lowerprint:]S[:gr(\?=aph:]{-128,}" + "666666666666666666666{}[:upperword:]|" + "nnnnnnnnnnnnnnnnnnnnnnnnnnB)c[:xdigit:]{-225,}{-4,}{-192,}" + "QQQQQQQQQQQQQQQ@@@@@@@@@@@@@@@@@@@@@@.", + 0, 0 }, + { "([:digit:]s{44,}{}{-31,}c{,-130}pP){-241,}UeN", 1, 0 }, + { "([^)((\?>\?#{}hK\"V2\?d][KKK(\?imsxim:KKKKKKKKKKKKKKKKKKKK[^" + "KKKKKKKKKWWWW[WWWWWWWWWWWWWWWWW)B])_l_3", + 1, 0 }, + { "[(^[(\?!*){[^,91}].j]*]L)*c|[:alpha:]&", 0, 0 }, + { "[^[[[^[777GGG(\?:W_U(\?imsxms:[:punct:]A]-)[:digit:][:" + "blankcntrl(\?(:]][:alnum:)])]WRRRRRRRRRRRRRRRRRRRRRRRRRRR]{" + "31,}[:xdigit:]][:xdigit:]))))))))))))))))))))))$[:xdigit:]", + 0, 0 }, + { "[:ascii:]m*[:punct:]#[(\?<!:punct:][:alpha:]-," + "7vyXeeeeeeeeeeeeeeeeeeeeeeeee^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" + "^%%%%%%%%%%%%%%%%%%%%%%%%%%%%[:digit:]''''''''''''''''')", + 0, 0 }, + { "([^*[(:punct:]9999999999999999999{147,}]j{,193}{171}Z-)){" + "208}0[:graph:]yDt", + 1, 0 }, + { "(dw[[:alpha:]U]ttt[tttttttttttttttttttt]Q^171e)[:xdigit:]/", + 1, 0 }, + { "[[^((\?#)Tqqqqqqqqqqqqqqqqqqqqqqqqq105++++++++++++++++++++++" + "++++b7V+7dit]])|D", + 0, 0 }, + { "{}P7.Ajh[:xdigit:]^[:blankc((\?(\?<=nt[rl:]FFF)-]){}o|a[:" + "grap(\?!h:]))PsssssssssssssssssssssssssssssssN^{-60,}Kb", + 0, 0 }, + { "[:alpha(\?(:]$!_+777777777777777777777777O)666)lll[^llllll[^" + "l{{{{{{{{{{{{{{{{{{{{{{|]{-217,}MoEl`7)^)LlU[:alph[a:]({-" + "241,27})]]{-212}{,249}n)X", + 1, 0 }, + { "[U|ajP[:alnum:]n[(:digit:]]W)[:graph:]b[:xdigit:].P", 0, 0 }, + { "(([:low(\?-imsx:erprint:]|{}[:ascii:][:gr(\?:aph:])>>>>>>>>>" + ">>>>{,-129}))\?{-226,}^P)R", + 2, 0 }, + { "[^[[nnnnnnnnnn(\?=nnnn(\?!nnnnnnnnnnnn(\?#nnnnnn{,-38}N){" + "202,}]$[:alnum:])]t][:alnum:[]^=w){237}][:alpha:]-[:alpha:]+" + "e", + 0, 0 }, + { "()[(\?(:digit):]+qc)O88888888{,151}aJ", 1, 0 }, + { "([^([(\?!sv(\?=)d]{-200,})N))]Z{-73,15}", 1, 0 }, + { "([\?\?\?\?|||||||||||(\?{||(\?=||||||||-}[))Ehhhhhhhhhhhhh{," + "202}&TcfL((\?:>)((\?!\?>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$8[:" + "alpha:]\\d])]C[:graph:]h*,\"\?u{|mU,a)[:blankcntrl:][:" + "lowerp(\?>rint:])PPnP+9.[:xdigit:]*PPjjjjjjjjjj~y<#*scf_\"^" + "e[:xdig(\?(i)t(:])~$y)^){-131,77}^L%", + 1, 0 }, + { "[^[(((\?>)$}h9$B5+yhU/" + "Nqh$YYYYYYYYYYYYYYYYYYYYYShK)3WHw1vMMMMMMMMMMMMM(\?=" + "MMMMMMMMMMMM[:alnum:]/" + ")dddddddddddd(dddddd\"e5zLW)+![:space:]+BHGHfAS]" + "\?IIIIIIIIIIIIIIII*&&&&&&&&&&&&&&&&&&)NNvwDteepjdm<<<<<<<<<<" + "<<<<<<<<<<<<<<<<<<<<${61,219}D][:digit:]0", + -1, 0 }, + { "[:punct:][{177,(\?=234}]ix9*)", 0, 0 }, + { "([^K{,3(\?<=4}]I)\?U)", 1, 0 }, + { "[([^[[[^([([^[^(\?=])X", 0, 0 }, + { "[:blankcntrl:(])qd_R\?{\?r[=\"[^[^6]vX8)a+{C%H84CK6Uy#E]sE{" + "208}", + 0, 0 }, + { "PPPPPPPPPPPPPPPPPPPPPPPPPPnnnnnnnnnn()[:upperword:]us", 1, + 0 }, + { "x{,46}[:graph:]LU{}CU)", 0, 0 }, + { "()-t|[^W{}][:lo[^werprint:]{}]\?b5", 1, 0 }, + { "()x5A", 1, 0 }, + { "[([^]-217)]s{-47,135}0000000000000000000000000000000{,-108}", + 0, 0 }, + { "[^((\?{[^L\?u]})f", 0, 0 }, + { "()[[^^(\?{y(\?=VF_(\?<=]D}))]-= {46,})^5bIEQ{,-96}Z", 1, 0 }, + { "([^{}f[:punct:]\"X%%%%%%%%%%%%%%%%%%%%]5{-194}A[:punct:]" + "mnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn+AAAAAAAAAA-)", + 1, 0 }, + { "(CCCCCCCCCCCCCCCCCCCC{-230}352{-182,-68}O4{})", 1, 0 }, + { "([^[^\?[:space:]$TTTTTTTTTTTTLLLLL[^LLLLLLLLLL[^({}{4,-179}]" + "]J] C]){}C{}{-224,})QQQQQQQQQQQQQQQQQ^", + 1, 0 }, + { "([[:alnum:]].){-155,-82}dzI{55,}^", 1, 0 }, + { "([[:alnum:](\?#{88,-178})[:graph:]NC\"pI[:punct:]rmWd5y^p+" + "gUP]YYYYYYYYYYYYYYYYYYYY~{,-62}{,200}{-109}{}+" + "333333333333333333333333333333{}p)^.hhhhhhhhhhhhhhh", + 1, 0 }, + { "[000000(\?mmsx:00000000000000000000000)M]]]]2*`[^]QQQQQQQQ(" + "\?<=QQQQQQQQQQQQQQQQQQQQQQQ])\"<h\?", + 0, 0 }, + { "[^((<g(\?>5j[bbbbbbb(\?{bb)o{}3(\?imxisx:E]g})YYYYY[:" + "blankcntr(\?#l:].(()w264[:ascii:]^)[:ascii:]G)&(n " + "{^PGn[:xdigit:])nv_e|]{-103,30}", + 3, 0 }, + { "[^(([(\?!{}@[^HCO[[^^D[|]{,-49}][:xdigit:]]c`4[:ascii(\?<!:]" + ")$66666666666)*)]PP$Z[:alpha:]{,-235}UK],(aT/" + "+6rbMqs60EloA)[:g(\?isx:raph:]!)]z$o{-24,}x1E[:blankcntrl:]" + "ZDFvk", + 1, 0 }, + { "[:blank(\?=cntrl:]US@.!\"[:digit:]*E)$16182", 0, 0 }, + { "[-{}x{3772[}][:(\?<=xdigit:][:u(\?#pperword:].W)aD)<pfN<b=C|" + "-{-38}EZdOP|!>ggggggggggggggg\\\\\\\\\\\\\\\\\\\\\\\\\\Ef[:" + "space:]\?][:ascii:]{21,}", + 0, 0 }, + { "([:xdigit:]W[:u(pperword(\?::]jS " + "[:upperword:]*)[:alpha:]nnnnnnnnnnn))-148}SSu", + 1, 0 }, + { "([^(\?!\?)[(:upperword:])Bx^x$~lCr6*)6", 1, 0 }, + { "[{,-78}Y[:xdigit:][^s(\?>]P[:space:])]YYYYYYYYY[:punct:][:" + "alnum:][:blankcntrl:]", + 0, 0 }, + { "([MMMMMM(\?(MMM)M(\?<=MMMMMMMMMMMMMMM[^M)]en][:punct:]-[:" + "alpha:]))Nr[:space:]", + 1, 0 }, + { "~=1([^(\?=(\?:l){}])j{-44}{-18}[^u[:graph:]]{-187,}[:xdigit:" + "]w[:alpha:])", + 1, 0 }, + { "[ccccc(\?>c(\?{cccc[ccccwetoCei+)w&-+{,-142}[:alpha:]" + "PP66io4(|zkA=],,,,,,,,,,,,,,,,,,,,,Lx5Cx{d2bb}]{188}U~~~~~~~" + "~~~~~~~~~~~~~~~~})", + 0, 0 }, + { "Q|0\"[:d(\?:igit:]^{,-174})", 0, 0 }, + { "[^[(\?>rh])]", 0, 0 }, + { "[ees{{{{{{{{{{{{{{{{{bbbbbbb4`ml******(\?=****+])", 0, 0 }, + { "((hdG[((\?<=:dig(it:])[^[:alpha:]$(\?sxi:)x{11390}[(\?{:" + "upperword:]~)i 8[:blankcn[trl:(])]+{,-183}Zqp", + 2, 0 }, + { "Dd{D8`+DW={-[53,1(\?<=71}])", 0, 0 }, + { "[:(\?(alpha:][:punct:])", 0, 0 }, + { ".LLLLLLLLLLLLLLLLLLLLLLLLLLLL{}pP[:punct:]x0CZ{30,}!!!(!!!!!" + "!!!!!!!!!!!!!!!!!!!!==@77.%[:graph:]D)", + 1, 0 }, + { "[^[^[[r(\?#]){-237,}RRRRRRRRRRRRRRRRRRRRRRRR[^Rll(\?!(\?{" + "lllll]", + 0, 0 }, + { "()*ooooooooooooooooooooyyyyyyyyyyyyyyy", 1, 0 }, + { "{,4(}D)JJJJJJJJJJJJJJJJJJJJJJJJJ", 1, 0 }, + { "((b.D{}[:al[pha:]{64}]{})==========================[:alnum:]" + "h>77b)!Ab", + 2, 0 }, + { "([^[^[^oooooooooooooooooooooo][:space:][:punct:]PeniKe*~$" + "g\?${>[:lowerprint:]w))))))))))))))){}yyyyyyyyyyyyyyyyyy]pP." + "|QhZ]{,190})sssssssssssssr+=[:blankcntrl:]" + "WWWWWWWWWWWWWWWWWWWWW", + 1, 0 }, + { "([*(\?{})hhhhhhhhhhhhhhhh]G{,-170}QdErrrrrrrc-" + "jjjjjjjjjjjjjjjjjjjjn+{-130,-10})PpDS@Bee", + 1, 0 }, + { "([:b(\?=lankcntrl:]))T[:alnum:]{-224}ywt", 1, 0 }, + { "([633(\?<=333(\?<=3333333333(333333)^\?]aGA)[:digi(\?>(\?{t:" + "])$[[:space:][:xdigit:])|8T\?',_{171}{}{113}b\?5kAv0/" + "7{})`huh>xM]C8pYRz]s$Eu08)", + 1, 0 }, + { "-(pP)[:alnum:]$^", 1, 0 }, + { "[^x(\?{{17681}]P*)U(_t/8E_\"iN})3333333", 1, 0 }, + { "(([^([[r(\?=[[^^*kx$][:alpha:]:::[:::::[^[^::::::::((\?{\?{:" + ":]).^p[:space:]}){52}{}]W{}fn", + 2, 0 }, + { "[:(\?>punct:]Ef[:xdigit:]x{c07b}{-50}Z{129,}YL1T`\\A)x[:" + "punc(\?=t:]e[:xdigit:]2c6E46Y)+n ", + 0, 0 }, + { "[^(\?!{,-79}[:punct:]'|}>,)][:blankcntrl:]{-118,-231}{-119,-" + "50}:XXXXXXXXXXXXXXXXX-~{}$txlB)3KFL", + 0, 0 }, + { "[^(([^fccccccccccccccccccc(\?<!ccccgQeKMfKzz]X$$$$$$$$$$$$$$" + "$$$$$$$$$$$$$$$$$[:l(\?<=(\?<=owerprint:]))s{-97}{}))EUi${,-" + "132}'{79}---------{,-93}77777777777777777[:lowerprint:].:H)[" + ":punct:]nnnnnncP\?s1:dGed{186}N@pppppppppppppppppppppP{-212," + "-110}[:space:][:lowerprint:]$S}7{-112,164}-*.{-184,}" + "OOOOOOOOOO]f\?", + 0, 0 }, + { "(([\?#(\?>)])qcU$Q7|82\?{})", 2, 0 }, + { "[^yyyyyyyyyyyyyyyyyyyy(\?#yyyyyyyyyyya][:ascii:]\?)", 0, 0 }, + { "(([((\?{)EEEE(\?<!EEEEE(\?:EEEEEE~)}){244,}" + "QQQQQQQQQQQQQQQQQQQ(\?>QQQQQQ(\?!QQQQQ][:digit:]\?))" + "99999999999999)[:digit:][:upperword:]b))PP{}{}", + 2, 0 }, + { "(K(c=B))", 2, 0 }, + { "(G`*s\?b[:g(raph:]))", 1, 0 }, + { "[^[([[[*QQQQQQQQQQQQQQQQ(\?=(\?=QQQQQQ(\?<!" + "QQQQQQQQZddddddddd((\?{\?>ddddddddddc{22,}iiiiiiiii(" + "iiiiiiiiiiiiiii(\?#iiiiiii[^i))\?\?\?\?\?\?]WWW)[:" + "lowerprint:])]{-60,202}+[:upperword:]f[:xdigit:][:alnum:]{,-" + "214})1~~~~~~~MMMMMMMMMMMMMMMMMM.", + 0, 0 }, + { "({-102,})A.", 1, 0 }, + { "[((((\?<!(\?[^>(\?#\?()))p\"JD.{}(\?>)))((\?{l(\?<=).'053][:" + "xdigit:]N+)})]WWWW%[:asc(\?{ii:]}))B[:alnum:]X){}s[:digit:]", + 0, 0 }, + { "x7&{139}WWWWWWWWWWWWWW[:blankcntr[^(\?<!l:]-71]\"{-167}cqkI)" + "[:dig[^it:]{}{}[:digit:]*[:punct:]-[l11111111111111111(\?(" + "111111111{175,-216}~[:alnum:]`+X1F)vCpWSp(\?>~[^n@f`````````" + "````)````````P])Y,N{}{}]{}pXF@)", + 0, 0 }, + { "G[([(\?(^)$])P]^[:alnum:]){,-48}[:blankcntrl:]{}", 0, 0 }, + { "[[^[^f(\?=f(\?<=fffffff[^fffffffff[^fffffffff(\?<=fff]){-" + "194,150}fx{e5a4}V", + 0, 0 }, + { "9[:xdigit(\?{:]})", 0, 0 }, + { "[^([[(\?>()$xxxxxxxxxxxxxx[xxxxxxxxxxxxxxxx((\?=aA)s13]])pp[" + "(\?>pppppppppppppppp|{}){20,}]b)]{-179,183}{-204,}[:ascii:])" + "]-11111111{}{,132}qooooooooooooooooooo{}${}|9t", + 0, 0 }, + { "([^[{}]\"[^6]*-{,-106}{}u]BR~8WG,U-)[:blankcntrl:]", 1, 0 }, + { "[''''''''(''''''''''z])c", 0, 0 }, + { "[^[(\?>])[:alnum:]r[:alnum:]+{,215}D]", 0, 0 }, + { "([({,127}7Qr(\?:z)pPNev%}(\?msximsx:4(\?<!){}&.D5555(\?<=" + "55555555555555555555i$[:xdigit:]){,-157}[:graph:]U[:punct:]" + "nn(\?=nnnnnnnnnnnn(\?>nn(\?:nnnnnnnn_U{}]E)):^" + "oooooooooooooooooooooooooooo)", + 1, 0 }, + { "[^(\?#)(\?<!k2z]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]BW[:alnum:][:" + "graph:]{157}Y]s$C)[:graph:]{,-189}", + 0, 0 }, + { "$+CCCCCCCCC[^CCCCCC(\?<=Ca=]r{-81}[:alpha:][:alpha:])E=", -1, + 0 }, + { "[(((\?=\?{([^(\?<=)])>!(([:alnum:]{252}{}})ffffffffffffl){}" + "A2r\?~ImE\"[:punct:]){}[:digit:]", + 2, 0 }, + { "([:blank[cntrl:]].t^P)", 1, 0 }, + { "[^[(\?:X])|rrrrrrrrrrrrrrrrrrrrrrrrrr*P]Q", 0, 0 }, + { "[[[^(\?{((\?<!))s})(\?<!A){14}(\?:L*+TTTTTTT]U{[^-12([\?!,}" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?)Y`Y)L]|]]|" + "]", + 0, 0 }, + { "hkXzf',]yP$+[:u(pperword:])", -1, 0 }, + { "(#[:blankcnt(\?iximsx:rl:])$QQQQQQ{}[:digit:])\?A", 1, 0 }, + { "(B{-34,})*{,106}", 1, 0 }, + { "[(\?{:graph:]})", 0, 0 }, + { "((){}{,63}[:punct:]^t[:space:])^17737", 2, 0 }, + { "([^[SSSSSSSSS[SSSSSSSSSSSSSSS[([[[{38,}]Jn][:alpha:]])])$'", + 1, 0 }, + { "[^({}{95})B{1(\?>15}]x{f779}ZZ,Wo)O[:alpha:][:lowerprint:]{" + "81,228}Q[:upperword:]", + 0, 0 }, + { "[[^[^()n[[[[[[[[[[[[^[[[[[[[[[[(\?: G)(\?{K![^m) " + "j(\?:C|((\?:n*Xlaa908:n$m,))[:xdigit:]x(\?{{1a5cd}" + "pppppppppppppp(\?(pppp)p(pQ)))" + "ddddddddddddddddddddddddddddddd]q[:alnum:(\?{]Ga})\?})@[:" + "lowerprint:]{,169}[:blankcntrl:][:graph:]]n{-76,}|U\"{,-54}" + "t]I{}{-64,-232}]\?].\?{-111,227}) " + "@hFp\?j=H$Wbu<{,209}De{,145}{206}-})[:blankcntrl:]", + 0, 0 }, + { "[^[^(LLLLLLLLLLLLLL[^L[L[:alpha:]3{,189}(\?#(\?>n){}^" + "EXXXXXXXXXXXXXXXXXXXXXXXXX]c*)^r=$WWWWWWWWWWWWW", + 0, 0 }, + { ")w###################", 0, 0 }, + { "{,121}[:d(\?(i)git:])E\?[:punct:]LLLLLLLLL[:ascii:]+", 0, + 0 }, + { "([]]]]]]]]]]]]][:space:]Jrt3o.]b)pwwwwwwwwwwwQfm~", 1, 0 }, + { "[+-{,-120}*(\?!()t*(\?(\?{>G)F)yd]V{}f<\?}){245}" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[:upperword:]", + 0, 0 }, + { "(DDDDDDDDDDDDDDDDDDDDDDDDDDDDDc[:space:][:pu[^nct:]{-11,12}[" + ":ascii:][:alpha:]{,155}P])", + 1, 0 }, + { "()ggggggg{-136,-21}", 1, 0 }, + { "([^((\?<=U\?)(\?=^^^^^^^^^^^[^^^^^^^^^^^^^///(\?#//[////////" + "////////////" + "(\?()#######b+]$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$^[:digit:])" + "\\U]Q8@}4d)\\U", + 1, 0 }, + { "A[:graph(\?::])-mo=U[:upperword:]" + "ttttttttttttttttttttttttttt", + 0, 0 }, + { "[^(((\?=\?im-m(sx:)c~~[^~~~~~~~~~~~~~(\?>~~~~~~~~~~~~~" + "SSSSSSSSSSSSSSSSSSSS]{51,}[:digit:]{,-179}N))kk[" + "kkkkkkkkkkkkkkg$)[(\?::punct:]zWl)]|)*", + 0, 0 }, + { "[((\?=()+A)][:graph:]x0B)[:graph:]", 0, 0 }, + { "(nR%B[:blankcntrl:]C=|en-[:digit:]n[:graph:]HHHH[HH]D\?%[:" + "digit:]MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.z(oF9zW8A7cfff(f))-[" + ":blankcntrl:][:blankcntrl:]A[:digit:])D{,-243}", + 3, 0 }, + { "([[()]]{,-251(})\?L)uw@", 2, 0 }, + { "\"|{(,-144})A.ooooooooo(ooooooFFFFFFFFFFFFF\?)n{,-18}", 2, + 0 }, + { "([^([(([[^([000000[0(0(\?!0(\?=0000000])45|E]", 1, 0 }, + { "[B[[[[[[[[[[[|{}*oKqv%(\?<=wsQ{1pMeK1^6%nLNqi<@ge][:punct:]=" + " M@* " + "D|NwL\\-" + "117\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"~" + "Qnd]h.O\"01x:[:alpha:]^){}D}\"", + 0, 0 }, + { "([[RRRRRRRRRRRRRRRRRRRRRRRRRRRRxpSrx{7d79}*oJ2`Ft{n1,3g:1H@" + "bT$D " + "&[n/" + "Cg)=ld@Ir{Fk>*4*`(\?>````````````````````(\?:`````.........." + "...........]]{,246})7 \"F4[^F|/g)]+e`rw@{,-69}H)", + 1, 0 }, + { "([(\?<=)X[:digit:]PP.[(\?#:((\?#\?#graph:])[:digit:][Q+)(N][" + ":alpha:]]f)[:graph:])+Elllllllllllllllll[:digit:]=)pP{uU-" + "20bzY|ZKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKt<c", + 1, 0 }, + { "[^(([^$(\?:(\?#w)[(\?::punct:]]d{-149,}[:ascii:])[:" + "blankcntrl:]@@@@@[@@@@@@@@@@@@@@[:graph:][:xdigit:]O[:alpha:" + "]2$-[:graph:])[:lowerprint:]-\?#S[:blankcntrl:][:alnum:]){-" + "77,}]d[:digit:]N5v+Sqqqqqqq^% " + "-I4]*.)^[:alnum:]" + "JDfjMRU7ttttttttttttjjjjjjjjjjjjjjjjjjjjjjCCCCCCCCCCCCCCCCCC" + "CD{,21}{0,67}[:graph:]{,208}B", + -1, 0 }, + { "(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[:ascii:])i{}[:lowerprint:]" + "epxxxxxxxxxxxxxx[:lowerprint:]r-", + 1, 0 }, + { "([(^w(\?!)()])-s", 1, 0 }, + { "[aIIIIIIIIIIIII(\?imsxims(\?=x:IIIIIIIm^NXXXXX(\?!(" + "\?isximsx:XXXXXXXXXXXXXS0]F)z))+" + "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr{,-237})" + "ZZZZZZZZZZZZZZZZZZZZZZ", + 0, 0 }, + { "(Z)[:alpha:]", 1, 0 }, + { "U#Z(=)", 1, 0 }, + { "([:lowerprint:][:punct:])1cVb*[:xdigit:]&&&&&&&&&&&&&&&&&&&&" + "&&&&O", + 1, 0 }, + { "()~K`3/[^*h[]G6[:upperw(\?()ord:]w)[:punct:]]{}", 1, 0 }, + { "[[[]V[:digit(\?>:])|l*KKKKKKKKKKKKKKKKK,,,,,,,[,,,s.{148,}" + "P33333][:lo(\?<!werprin(\?!t:]ZZZZZZZZZZZZZZZZZZZZZZZ]{,-" + "229}{-160,}){,-211}XPPP].{}z[:alnum:][:alpha:(\?=]t{166,}" + "uuuuu6]i*p(m))[:space:]E|S", + 1, 0 }, + { "[^(h(\?(\?({#2})(\?(\?#>Q){,57}%[:digit:]" + "\?\?\?\?\?\?\?\?\?\?.[)]]d{)-49,}f)^O{,68})\?C", + 0, 0 }, + { "(}u])18621", 1, 0 }, + { "[:as(\?=cii:][^(\?=)(S-{.F-[:punct:]3-105^[:lowerprint:]" + "111111111111111111111111---)][:alnum:][:ascii:]JJJJJwHSk", + -1, 0 }, + { "[^3>>>>>>-sZ^^^^(\?>]Y[:di(\?(\?imxim:#git:]{-158,-102}[:" + "punct:]{}{87,})))[:upperword:]", + 0, 0 }, + { "[(\?<!^r]$W){}*[:alpha:].[:digit:]", 0, 0 }, + { "[:ascii(\?::[^])X]-", 0, 0 }, + { "[([^]Z)[:upperword:]N{}*[:graph:]*^", 0, 0 }, + { "([[(\?#^[(:graph:]]){205,}[:gr(aph:]T%]^" + "MMMMMMMMMMMMMMMMMMMM){) <v\\[:digit:])", + 1, 0 }, + { "[^Y.h~b(\?<=~P{(\?=169,65}\?[^\?\?\?\?\?\?\?\?\?[" + "\?\?\?\?\?\?\?\?\?K\"s`[yT7oP[:alpha:]{})]zrrrrrrrrrrrrrr)]" + "KKKKKKKKKKKKKKK[:digit:]S][:lowerprint:][:digit:]", + 0, 0 }, + { "(s)", 1, 0 }, + { "[u(\?!uuuuuuuuuuuuuuuuuuuu[:digit:]{,48}[:graph:]WL[:alnum:]" + "]v=_)VN>{AjBBBBBBBBBBBBBBBBBBBBBBB[:upperword:]`'W)", + 0, 0 }, + { "[^([[()DN1[^][|]\?]{-104,}])[:space:]][:lowerprint:]r[:" + "alpha:].DU", + 0, 0 }, + { "[^((33333333333333333333333(\?<=3333333D))" + "kkkkkkkkkkkkkkkkkkkkkkk[k[:alpha:]])]X+", + 0, 0 }, + { "[({,-17})[@e{220,(\?#41}])]]{-213,-225}", 0, 0 }, + { "[[^(\?#[(\?:^[[(\?(^]))]])]vvvvvvvvvvvvvvvvvvvvv{,96}|m]{-" + "79,248}[:alpha:])", + 0, 0 }, + { "([[(\?imsisx:^}$,-[:al(\?>num:]Xqqqqqqqqqqqq{-185,154}]b#+T)" + "{-241,})A{-27}[(\?<!:lowerprint:]X)[:punct:]ME-]+" + "BBBBBBBBBBBBBBBBa|{-40}M8mhgD 0HU]{16})", + -1, 0 }, + { "[^(\?>([\?()(\?#))]--R1rk^UnP.[(\?!:digit:]])^)[:upperword:]" + "{}0000000000000000000000000000000~U{-139,-19}z<L-228", + 0, 0 }, + { "()-:=3uE$[:alnum:]bP%{-210,}", 1, 0 }, + { "(U)7777]]]]]]]]]]]]]]]]]]]]]]]]]]]]]c::AA[:alpha:]{,3}f1{" + "NzH@3lTf{}{", + 1, 0 }, + { "[C{(\?>})RR(\?=R<]p'N~&.-})6]", 0, 0 }, + { "[^\?[^(\?(lFt]).[^7Q-])kkkkkkkkkkkk]XTFy\"1Deiv!,'xVK", 0, + 0 }, + { "[^$[^[:xdigit:](\?{*{245,99}h8v(\?!)]]u)Z[:punct:]})[:alnum:" + "]+|[:blankcntrl:]u{}[:lowerprint:]+bBJ4+k-v{-116}", + 0, 0 }, + { "S)f{,180}[:graph:]&{12,244}", 0, 0 }, + { "(([[(.()[^^{80(\?>(\?<=,235})ddddddddd[^ddddddddd(\?<=d.__B{" + "36}````````````````(\?:```(\?>```````,,,,,,,(\?:,,)P$U,[:" + "xdigit:])zzzzzzzzzzzzz]UUUU[uB]n<&[(:ascii:].][:alnum:])\?S]" + "{})d{138,}s9========[:lowerprint:]]OOOOOOOOOOOOOOO|" + "yyyyyyyyyyyyyyy$LZ[:lowerprint:]EEEEEEE[:ascii:][:punct:]" + "VpP^{-48}D){,46}x))2P))a[:lowerprint:]r", + 2, 0 }, + { "[^(((\?<!):())PPPPPPPPPPPPPPP(\?=[PPPPPPP(\?{PPPPPPPP$)})" + "77777777777777777]{,-57}::::::::::::(::::::::::::::::)]g{89}" + "__________________[:xdigit:]l[:punct:])N", + 1, 0 }, + { ":02-k\?p3I7aEhJ\\265-[:space:]pP[:space:]x0F[:alnum:]aM4[:" + "lowerprint:]sA@@@@@@@@@@@@@@@@@@@@@@@@@@@@", + -1, 1 }, + { "a[:upper(\?{word:]})X{-173,}-2F[:lowerprint:]", 0, 0 }, + { "u,w<g*Q002S{,130}{239}[:lower(print:]cr{-165,}#$k<L/" + "&)[:blankcntrl:]aaaaaaaaaaaaaaaaaaaaaa[:ascii:]", + 0, 0 }, + { "(xFA^{-161,93})U[:xdigit:]", 1, 0 }, + { "[^(\?=]{})mE`", 0, 0 }, + { "[[((\?(\?#:alnum:]])x6CS[:digit:]{-197,}.)N", 0, 0 }, + { "[^(\?![])C*[:upp(erword:])-176]", 0, 0 }, + { "[[^[[^[55555555555555555555555555(\?>555(\?<!555)S][]]A[:l(" + "\?>owerp(rint:]])]*", + 0, 0 }, + { "Au)khgzAfXIZoZ=g[:digit:]){,186}Upvf=x<]Tbd5Rq\?.", 0, 0 }, + { "b{-176,}B^[:bla(\?(<!nkcntrl:]{-6,133}#B " + ":)<<<<<<<<<<<<<<<<<<<)[:alnum:]$}}}}}}}}}}}}}}}}}}}}}}}[:" + "xdigit:]tw", + 0, 0 }, + { "(4IIIII(IIIIIIIIIIIIIIIII{})W{-152,-238}){,-56}^{-142,}", 2, + 0 }, + { "[^([[(\?(\?(!)>>>>>>>>>>>>>(>>>>>>>>D)Ix{(1(\?imxmsx:762)c})" + ")A)[[[[[[[[[[[[[[5Rp]DDDDDDDDDDDDDDDDDDDD]Us+\\w[:digit:]{-" + "47}[:xdigit:][:blankcntrl:])ddddddddddddddd[^ddddddddddddd[:" + "digit:]|]]*{-165,-230}{-212}{53,}]\?", + 0, 0 }, + { "[^[^]]|[:(\?:alnum:])}}}}}}}}}}}}}}}}}}}}", 0, 0 }, + { "VVVVVVVVVVVVVVVVVVVVVVVVVVVV[:d(i(\?#git:])){{{{{{[:digit:]" + "ZfQ55555555{}Z", + 0, 0 }, + { "[L][:blankcnt(\?((\?=rl:(\?=]){-35,[^}){)eJb>>>>>>>>>>>>>>>>" + ">>>>>>$ [:xdigit:]l0Tv2Tw2@C[:space:]Zc/{*)>]N3j~.dMBBBB", + 0, 0 }, + { "[[^(\?>(([]))])[:graph:]]{65,}as#Q:lQ", 0, 0 }, + { "[^[fPPUUUUUUUUUUU(\?#UUU[^UUUUUU(\?<=" + "UUUUUUUUUGGGGGGGGGGGGGGGGGGG((\?{\?=GGGGGG.MK))+]+)&UxFW)" + "rwv\?@D.", + 0, 0 }, + { "{-(60,})m", 1, 0 }, + { "b[(])^w", 0, 0 }, + { "[][^qVs(\?:(p])X)\?'", 0, 0 }, + { "()8", 1, 0 }, + { "(t[:punc[^t:(\?{][:blankcntrl:])})[^8\?]z*]", 1, 0 }, + { "[:lowerprint:])[:graph:]lppppppppppppppppppppppppppppf", 0, + 0 }, + { "[:alph(a:])[:ascii:]g +z-Bc-U{,%Gk", 0, 0 }, + { "u[:graph:(\?=]*)W:::", 0, 0 }, + { "([:alnum(:])l)", 1, 0 }, + { "[[[}}}}}}}}(\?<!}}}}}}}+(\?{),,,,,,,,,,,,,,(\?!,,,,,,,,]" + "99999999999&R[:ascii:]ZZZZ-{-10,}{96}Ed*][:graph:])]}){}{}G{" + "-9,}", + 0, 0 }, + { "([^[{}]]Z[[^:graph:]{-47}55555555555555555555555555555[:" + "ascii:]s]6,$:3qAew1Y)+)[:punct:]", + 1, 0 }, + { "[[[[[([[[[[[[[[[[[[[[[[[[[[[[[8!1i]')", 0, 0 }, + { "([((\?(\?#>)(\?{,)At]%M9FSq5)EB", 1, 0 }, + { "(}````````````````(``{210,})[:(\?#space:]P[:digit:])PP.{-" + "227,}$pK~mm ImR|{,51}[:alnum:]<)[:alpha:]", + 2, 0 }, + { "[^(\?<=])[:digit:]", 0, 0 }, + { "[^'''''''{(\?:178,}e{,16}$QQQQQQQQQQQQQQQQQQQQQQQ$])", 0, + 0 }, + { "[^(\?>@K*)(\?#d18]{78,}B)[:digit:]{-193,}=wg{,59}", 0, 0 }, + { "[^.{156,}!(\?<=!!!!!!!!!!!!!!(\?{!(\?(!!!!!!!!!!!!!)})" + "TTTTTTTTTTTTTTTTTTTTTTTTTTTTT[^}}}}}}}}}}}})}}}}}}}}}}}}}]])" + "{}^L#%-{}FC", + 0, 0 }, + { "(eeeee{-169,-100}-fa[:upperword:]N)$Nellllllllllllll", 1, + 0 }, + { "[[(\?!())\?[(\?!:alnum:]e{,28}M])[:punct:]" + "CCCCCCCCCCCCCCCCCCCC]{-150,}{-167}", + 0, 0 }, + { "[[@[@(\?#@[@]P]Z{')]{-186,117}]+)7f-", 0, 0 }, + { "\\Q+kD}]AEM)u ", 0, 0 }, + { "([(\?{(\?=:::::::::::::&){,210}]^})P{-31,}8[:space:]C[:" + "alnum:][:a(scii:]z|[:upperword:])[:alnum:][:graph:])zr~Zk", + 1, 0 }, + { ".[:space:]e[:g(\?{(\?{raph:]})})@@@@@@@@@@@@@wb|~k", 0, 0 }, + { "()ooooooooo\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"[:graph:]", 1, + 0 }, + { "[^64h(\?(@Eyw][:xdi[git:]pP%%%%%u(uuu[:up[perword:]`8Utdh{)}" + "]]))lW[:punct:]W.hhhhhhhhhhhhhhhhhhhhhhhh'm<<}O8`ZXtG.$", + 1, 0 }, + { "BPP[:digit:]bbbbbbbbbbb(bb)S+[:alnum:]", 1, 0 }, + { "um.[:ascii((\?#\?!:])*)+KKKKKKKKKKKKKKKKKKKKKKKKKS.=<Bf", 0, + 0 }, + { "", -1, 0 }, + { "(()$[:lowerprint:][:s[pace:]2]bbbbbbbbbyoooooooooooooooooo*{" + "39,}$')qV`AcH>,eDl", + -1, 0 }, + { "(()[^])e{-241,}", -1, 0 }, + { "()[:alpha:]rliiiiiiii[:alnum:]Mb*QW9N.>\?{115,}&u*j", -1, + 0 }, + { "()[]p", -1, 0 }, + { "(I[^]pfL)$[:punct:]", -1, 0 }, + { "([])>>>>>>>>>>[:alnum:]", -1, 0 }, + { "([])O\\\\\\\\\\\\\\fffffffffffffffffffffff=s6jCZy/" + "b+ir2'*{151,}", + -1, 0 }, + { "([])nnnnnnnnnnnnnnnnnnnnnnnnnn[:xdigit:]^N$f", -1, 0 }, + { "([]M)[:lowerprint:]a(pg$Z[:punct:])77777777777.", -1, 0 }, + { "([]XXXXXXXXXXXXXXXXXXXXXX-===========)", -1, 0 }, + { "([]lkX{-224}[:blankcntrl:]$gPKIZlSC#F@XX " + "I'^}{234}yZm)uuuuuuuuuuuuuuuuuuuuuurS", + -1, 0 }, + { "([^0kYkg9])IIIIIIIIIIIIIIIIIIIIII/" + "{(192,-118}l+FoSD6\?A)c[:xdigit:]`````````````````e-{-4,-" + "170}x{4620}Z[:upperword:]", + -1, 0 }, + { "([^[^[^()(\?>){}B]XYF+#[:alpha:]{-85((,-55[^}t]n).{,-33}]](" + "bQJ!|O+{175,})RFh)Z+^.{137,}:VpP[:alpha:]-MceqVVkkkk(" + "kkkkkkkkkkkkkkkkkk)" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?{-" + "115,-67})``````````````````````````````", + -1, 0 }, + { "([^]EzU[:alnum:]+^^^^^^^^^^^^^^^^^^^)[:xdigit:]HHHHHHHH$" + "66666666666666666666666666666666UUUUUUUUUUUUUUUUUUUUL{}iiii{" + "-76}X", + -1, 0 }, + { "([^]~~~~~~~~~~{240,})]NOp", -1, 0 }, + { "(sb)[:digit:]VVVVVVVVx{9569}52,|]", -1, 0 }, + { "(x{19762}){}", -1, 0 }, + { "-[:xdigit:][]", -1, 0 }, + { "121|", -1, 0 }, + { "141[:xdigit:][:lowerprint:]{24}{59,191}[:digit:]/", -1, 0 }, + { "G[^],,,,,,,,,,,,,+\"DiX", -1, 0 }, + { "Gm(ho9:\"8{-188,-200}Z[:blankcntrl:]{,171}" + "\?\?\?\?\?\?\?\?\?\?\?[:blankcntrl:]LLLLLLLLLLLLLLLLLLLLLLL{" + "}^[:graph:][:blankc(\?#ntrl:])w", + -1, 0 }, + { "N\"\"\"\"\"\"\"-------------------------|[:alnum:]" + "AAAAAAAAAAAAAAAAAAAAf\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?", + -1, 0 }, + { "U{-30,}^\?\?\?", -1, 0 }, + { "W^*04rAY(Ee*>[^o3[]]_)", -1, 0 }, + { "X[^]}*C[:alnum:]", -1, 0 }, + { "[${,-3}]+^\?[|x8A|][:space:]'''''['''''" + "JJJJJJJJJJJJJJJJJJJJJJJJJJJJJyl}.Y7G]", + -1, 0 }, + { "[()&[&&&]\?\?[" + "\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?" + "pg%k8ug`Wqk4|NR{h[CK5Ez=]jHpQw&`{:]{,91}D", + -1, 0 }, + { "[(\?#(\?:)[)([\?>)(\?>(\?:[:alnum:])]G]{85}[^)w]N]gYrUs|", + -1, 0 }, + { "[(\?<=)[:digit:]\?]{152,}VR|", -1, 0 }, + { "[****(\?>**********(\?<!*******Q)Vr){[^25,}*:" + "FFFFFFFFFFFFFFFFFFFFFFFF(\?{FFFF(({}D]|", + -1, 0 }, + { "[:ascii:]+{124,}:*]\?$-{92}D[:lowerprint:]``````````````````" + "```", + -1, 0 }, + { "[:ascii:]\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?A<", -1, 0 }, + { "[:blankcntrl:]p\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?$" + "\?TTTTTTTTTTTTTTTTT[:ascii:][:upperword:]", + -1, 0 }, + { "[:punct:]{254}DDDDDDDDDDDDDDD@[:alpha:]Z\?\?-----R", -1, 0 }, + { "[:upperword:]J\?\?nqCAdfyW5", -1, 0 }, + { "[:upperword:]{-39}|", -1, 0 }, + { "[:xdigit:]^\?", -1, 0 }, + { "[Z*e ]NdmP\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?", -1, 0 }, + { "[[:punct:]q]ex{15625}-", -1, 0 }, + { "[[[^([^L((\?{b(\?=C\?]-134{,-207}[:ascii:]Hz}XIz}|", -1, 0 }, + { "[[^V(\?:(\?<!(\?>))TTTTTTTTTTTTTTTTTTTTTTT)[:punct:][:digit:" + "]]GGGGGGGGGGGGGGGGGGGGG,]|.{-224}{96}{239,}1", + -1, 0 }, + { "[[^^PP]{,-222}{182}{141}]zFD}-.", -1, 0 }, + { "[] Hn&[:xdigit:][:upperword:]f", -1, 0 }, + { "[]$.B", -1, 0 }, + { "[]&&&&&&&&&&&&&&&&&&&&&&&", -1, 0 }, + { "[]()[:xdigit:]er063{132,140}$", -1, 0 }, + { "[]+1434", -1, 0 }, + { "[]-", -1, 0 }, + { "[]-#yyK", -1, 0 }, + { "[]-(S$5)AxbdTKO[:alnum:]", -1, 0 }, + { "[]2883", -1, 0 }, + { "[]2dhd-[:alpha:]" + "sssssssssssssssss55555555555555555555555555555555Z[:punct:]", + -1, 0 }, + { "[]4", -1, 0 }, + { "[]44444444444444444G", -1, 0 }, + { "[]\?", -1, 0 }, + { "[]A", -1, 0 }, + { "[]Gap8bc", -1, 0 }, + { "[]OOOO", -1, 0 }, + { "[]PP", -1, 0 }, + { "[]QQ", -1, 0 }, + { "[]WaFaGO,o", -1, 0 }, + { "[]Z", -1, 0 }, + { "[][:alpha:]|[:digit:]Ls$I-Ff~+xA3e", -1, 0 }, + { "[][:ascii:]-218", -1, 0 }, + { "[][:ascii:]N}}}}}}}}}}}}}}}-{137,}8682", -1, 0 }, + { "[][:lowerprint:]Ur", -1, 0 }, + { "[][:space:]15097", -1, 0 }, + { "[][:xdigit:]", -1, 0 }, + { "[]dpSSSSSSSS", -1, 0 }, + { "[]e13768", -1, 0 }, + { "[]gT", -1, 0 }, + { "[]h", -1, 0 }, + { "[]n", -1, 0 }, + { "[]vvvvvvvvvvvvvvvvvvvvvvvvvv*[:xdigit:]", -1, 0 }, + { "[]{,-212}1111111111111111111C3821", -1, 0 }, + { "[]{-128,}hc", -1, 0 }, + { "[]{-181,}&[:xdigit:].\?}}}}}}}}}}}}}}}}}}}}}}", -1, 0 }, + { "[]{}F&}i`7|ZAH", -1, 0 }, + { "[^(\?())u{196,}pP][r^ndddddddddddddddddddddd]{31,246}\?J", + -1, 0 }, + { "[^.ii.1-S]lwwwwwwwwwwwwwwwwww[^wwwwwwwwwwwwww[:alnum:]DOpP+<" + "N][^]44{179}{-194,56}", + -1, 0 }, + { "[^2[:alnum:]]\?t\?\?", -1, 0 }, + { "[^[((\?{[^^<<<<(\?(\?<!{)})(\?<!]{,184}{-213}|", -1, 0 }, + { "[^[^[]\?{89,}PPsvf{[:space:]]]vd{161,}", -1, 0 }, + { "[^[^].]+{0}s", -1, 0 }, + { "[^]${}", -1, 0 }, + { "[^]([:punct:]),%[:xdigit:]w^0\?{-233}", -1, 0 }, + { "[^]-", -1, 0 }, + { "[^].^", -1, 0 }, + { "[^]6743", -1, 0 }, + { "[^]JD", -1, 0 }, + { "[^]N=[:upperword:]zzzzzzzzzzzzzzzzz.", -1, 0 }, + { "[^]OLz_6", -1, 0 }, + { "[^]PP[:digit:]0eBEx=", -1, 0 }, + { "[^]SHzuKp", -1, 0 }, + { "[^][:upperword:]{111}-TpmXw", -1, 0 }, + { "[^]^''''''''z{-73,}", -1, 0 }, + { "[^]^{,141}e", -1, 0 }, + { "[^]aaaaaaaaaaaaaaaaaaa{-98,43}", -1, 0 }, + { "[^]f", -1, 0 }, + { "[^]l", -1, 0 }, + { "[^]n\"Wt", -1, 0 }, + { "[^]pPZ\?q+m0LJ+", -1, 0 }, + { "[^]p[:upperword:]L:", -1, 0 }, + { "[^]q\?{,-18}-", -1, 0 }, + { "[^]s[:space:(\?<=]$", -1, 0 }, + { "[^]{,58}t", -1, 0 }, + { "[^]{255,}JJJJJJJJJJJJJJJJJJJJJJJJJJ", -1, 0 }, + { "[^]{45}", -1, 0 }, + { "[^]{W", -1, 0 }, + { "[^]{}{-22}", -1, 0 }, + { "[^]{}{}{}[:xdigit:]+", -1, 0 }, + { "[^]|9{,-108}{}.LVIJJJJJJJJJJJJJJJPP", -1, 0 }, + { "[^{,-254}]|", -1, 0 }, + { "[o(\?{(\?<=}[))f++++++++++++++++" + "777777777777777777777777yzPPs]" + "\?\?dRRRRRRRRRRRRRRRRRRRRRRRRRRRR&]>%fffffffffff", + -1, 0 }, + { "aW|", -1, 0 }, + { "cT{}[]C^r2``tm", -1, 0 }, + { "kkkkkkkkkkkkkkkkkkkkkkk[:blankcntrl:]|{}3{26,}{151,}[:punct:" + "]JJJlH$gP%(2WUE%%%%%%%%%%%%%%%%%%%%a){ibf{}\?", + -1, 0 }, + { "lZ\?\?\?\?\?\?\?\?\?\?\?-P2eZt[:punct:]", -1, 0 }, + { "vF3qn[^]N.", -1, 0 }, + { "wwwwwwwwwwwwww{-176,}275[^]>." + "UUUUUUUUUUUUUUUUUUUUeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee2$Yd", + -1, 0 }, + { "{-197,223}bf]]]]]]]]]]\?&}/s\?\?~c", -1, 0 }, + { "{-37,}EpP|", -1, 0 }, + { "{}@]a[][:xdigit:]z{a", -1, 0 }, + { "}02|", -1, 0 }, + { "}}}}}}}}}(}}){}[llll]^N|", -1, 0 }, + }; + unsigned int i; + int r; + + UNUSED(state); + +#ifdef HAVE_REGEX_H + /* + * Check if we get the expected response. + */ + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + regex_t preg; + + memset(&preg, 0, sizeof(preg)); + r = regcomp(&preg, tests[i].expression, REG_EXTENDED); + if (((r != 0 && tests[i].expect != -1) || + (r == 0 && tests[i].expect == -1)) && + !tests[i].exception) + { + } else if (r == 0 && + preg.re_nsub != (unsigned int)tests[i].expect && + !tests[i].exception) + { + tests[i].expect = preg.re_nsub; + } + if (r == 0) { + regfree(&preg); + } + } +#endif /* ifdef HAVE_REGEX_H */ + + /* + * Check if we get the expected response. + */ + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + r = isc_regex_validate(tests[i].expression); + if (r != tests[i].expect) { + print_error("# %s -> %d expected %d\n", + tests[i].expression, r, tests[i].expect); + } + assert_int_equal(r, tests[i].expect); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(regex_validate) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/result_test.c b/tests/isc/result_test.c new file mode 100644 index 0000000..cec195b --- /dev/null +++ b/tests/isc/result_test.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/result.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* convert result to identifier string */ +ISC_RUN_TEST_IMPL(isc_result_toid) { + const char *id; + + UNUSED(state); + + id = isc_result_toid(ISC_R_SUCCESS); + assert_string_equal("ISC_R_SUCCESS", id); + + id = isc_result_toid(ISC_R_FAILURE); + assert_string_equal("ISC_R_FAILURE", id); +} + +/* convert result to description string */ +ISC_RUN_TEST_IMPL(isc_result_totext) { + const char *str; + + UNUSED(state); + + str = isc_result_totext(ISC_R_SUCCESS); + assert_string_equal("success", str); + + str = isc_result_totext(ISC_R_FAILURE); + assert_string_equal("failure", str); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_result_toid) +ISC_TEST_ENTRY(isc_result_totext) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/safe_test.c b/tests/isc/safe_test.c new file mode 100644 index 0000000..a3f01fe --- /dev/null +++ b/tests/isc/safe_test.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* ! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/safe.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test isc_safe_memequal() */ +ISC_RUN_TEST_IMPL(isc_safe_memequal) { + UNUSED(state); + + assert_true(isc_safe_memequal("test", "test", 4)); + assert_true(!isc_safe_memequal("test", "tesc", 4)); + assert_true( + isc_safe_memequal("\x00\x00\x00\x00", "\x00\x00\x00\x00", 4)); + assert_true( + !isc_safe_memequal("\x00\x00\x00\x00", "\x00\x00\x00\x01", 4)); + assert_true( + !isc_safe_memequal("\x00\x00\x00\x02", "\x00\x00\x00\x00", 4)); +} + +/* test isc_safe_memwipe() */ +ISC_RUN_TEST_IMPL(isc_safe_memwipe) { + UNUSED(state); + + /* These should pass. */ + isc_safe_memwipe(NULL, 0); + isc_safe_memwipe((void *)-1, 0); + + /* + * isc_safe_memwipe(ptr, size) should function same as + * memset(ptr, 0, size); + */ + { + char buf1[4] = { 1, 2, 3, 4 }; + char buf2[4] = { 1, 2, 3, 4 }; + + isc_safe_memwipe(buf1, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + + assert_int_equal(memcmp(buf1, buf2, sizeof(buf1)), 0); + } + + /* + * Boundary test. + */ + { + char buf1[4] = { 1, 2, 3, 4 }; + char buf2[4] = { 1, 2, 3, 4 }; + + /* + * We wipe 3 elements on purpose, keeping the 4th in + * place. + */ + isc_safe_memwipe(buf1, 3); + memset(buf2, 0, 3); + + assert_int_equal(memcmp(buf1, buf2, sizeof(buf1)), 0); + } +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(isc_safe_memequal) +ISC_TEST_ENTRY(isc_safe_memwipe) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/siphash_test.c b/tests/isc/siphash_test.c new file mode 100644 index 0000000..5e93980 --- /dev/null +++ b/tests/isc/siphash_test.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <sched.h> +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/siphash.h> + +#include "siphash.c" + +#include <tests/isc.h> + +const uint8_t vectors_sip64[64][8] = { + { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72 }, + { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74 }, + { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d }, + { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85 }, + { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf }, + { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18 }, + { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb }, + { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab }, + { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93 }, + { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e }, + { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a }, + { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4 }, + { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75 }, + { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14 }, + { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7 }, + { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1 }, + { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f }, + { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69 }, + { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b }, + { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb }, + { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe }, + { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0 }, + { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93 }, + { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8 }, + { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8 }, + { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc }, + { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17 }, + { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f }, + { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde }, + { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6 }, + { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad }, + { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32 }, + { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71 }, + { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7 }, + { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12 }, + { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15 }, + { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31 }, + { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02 }, + { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca }, + { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a }, + { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e }, + { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad }, + { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18 }, + { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4 }, + { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9 }, + { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9 }, + { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb }, + { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0 }, + { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6 }, + { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7 }, + { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee }, + { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1 }, + { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a }, + { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81 }, + { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f }, + { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24 }, + { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7 }, + { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea }, + { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60 }, + { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66 }, + { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c }, + { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f }, + { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5 }, + { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95 } +}; + +const uint8_t vectors_hsip32[64][4] = { + { 0xa9, 0x35, 0x9f, 0x5b }, { 0x27, 0x47, 0x5a, 0xb8 }, + { 0xfa, 0x62, 0xa6, 0x03 }, { 0x8a, 0xfe, 0xe7, 0x04 }, + { 0x2a, 0x6e, 0x46, 0x89 }, { 0xc5, 0xfa, 0xb6, 0x69 }, + { 0x58, 0x63, 0xfc, 0x23 }, { 0x8b, 0xcf, 0x63, 0xc5 }, + { 0xd0, 0xb8, 0x84, 0x8f }, { 0xf8, 0x06, 0xe7, 0x79 }, + { 0x94, 0xb0, 0x79, 0x34 }, { 0x08, 0x08, 0x30, 0x50 }, + { 0x57, 0xf0, 0x87, 0x2f }, { 0x77, 0xe6, 0x63, 0xff }, + { 0xd6, 0xff, 0xf8, 0x7c }, { 0x74, 0xfe, 0x2b, 0x97 }, + { 0xd9, 0xb5, 0xac, 0x84 }, { 0xc4, 0x74, 0x64, 0x5b }, + { 0x46, 0x5b, 0x8d, 0x9b }, { 0x7b, 0xef, 0xe3, 0x87 }, + { 0xe3, 0x4d, 0x10, 0x45 }, { 0x61, 0x3f, 0x62, 0xb3 }, + { 0x70, 0xf3, 0x67, 0xfe }, { 0xe6, 0xad, 0xb8, 0xbd }, + { 0x27, 0x40, 0x0c, 0x63 }, { 0x26, 0x78, 0x78, 0x75 }, + { 0x4f, 0x56, 0x7b, 0x5f }, { 0x3a, 0xb0, 0xe6, 0x69 }, + { 0xb0, 0x64, 0x40, 0x00 }, { 0xff, 0x67, 0x0f, 0xb4 }, + { 0x50, 0x9e, 0x33, 0x8b }, { 0x5d, 0x58, 0x9f, 0x1a }, + { 0xfe, 0xe7, 0x21, 0x12 }, { 0x33, 0x75, 0x32, 0x59 }, + { 0x6a, 0x43, 0x4f, 0x8c }, { 0xfe, 0x28, 0xb7, 0x29 }, + { 0xe7, 0x5c, 0xc6, 0xec }, { 0x69, 0x7e, 0x8d, 0x54 }, + { 0x63, 0x68, 0x8b, 0x0f }, { 0x65, 0x0b, 0x62, 0xb4 }, + { 0xb6, 0xbc, 0x18, 0x40 }, { 0x5d, 0x07, 0x45, 0x05 }, + { 0x24, 0x42, 0xfd, 0x2e }, { 0x7b, 0xb7, 0x86, 0x3a }, + { 0x77, 0x05, 0xd5, 0x48 }, { 0xd7, 0x52, 0x08, 0xb1 }, + { 0xb6, 0xd4, 0x99, 0xc8 }, { 0x08, 0x92, 0x20, 0x2e }, + { 0x69, 0xe1, 0x2c, 0xe3 }, { 0x8d, 0xb5, 0x80, 0xe5 }, + { 0x36, 0x97, 0x64, 0xc6 }, { 0x01, 0x6e, 0x02, 0x04 }, + { 0x3b, 0x85, 0xf3, 0xd4 }, { 0xfe, 0xdb, 0x66, 0xbe }, + { 0x1e, 0x69, 0x2a, 0x3a }, { 0xc6, 0x89, 0x84, 0xc0 }, + { 0xa5, 0xc5, 0xb9, 0x40 }, { 0x9b, 0xe9, 0xe8, 0x8c }, + { 0x7d, 0xbc, 0x81, 0x40 }, { 0x7c, 0x07, 0x8e, 0xc5 }, + { 0xd4, 0xe7, 0x6c, 0x73 }, { 0x42, 0x8f, 0xcb, 0xb9 }, + { 0xbd, 0x83, 0x99, 0x7a }, { 0x59, 0xea, 0x4a, 0x74 } +}; + +ISC_RUN_TEST_IMPL(isc_siphash24) { + UNUSED(state); + + uint8_t in[64], out[8], key[16]; + for (size_t i = 0; i < ARRAY_SIZE(key); i++) { + key[i] = i; + } + + for (size_t i = 0; i < ARRAY_SIZE(in); i++) { + in[i] = i; + isc_siphash24(key, in, i, out); + assert_memory_equal(out, vectors_sip64[i], 8); + } +} + +ISC_RUN_TEST_IMPL(isc_halfsiphash24) { + UNUSED(state); + + uint8_t in[64], out[4], key[16]; + for (size_t i = 0; i < ARRAY_SIZE(key); i++) { + key[i] = i; + } + + for (size_t i = 0; i < ARRAY_SIZE(in); i++) { + in[i] = i; + isc_halfsiphash24(key, in, i, out); + assert_memory_equal(out, vectors_hsip32[i], 4); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_siphash24) +ISC_TEST_ENTRY(isc_halfsiphash24) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/sockaddr_test.c b/tests/isc/sockaddr_test.c new file mode 100644 index 0000000..c65ed76 --- /dev/null +++ b/tests/isc/sockaddr_test.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/netaddr.h> +#include <isc/print.h> +#include <isc/sockaddr.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test sockaddr hash */ +ISC_RUN_TEST_IMPL(sockaddr_hash) { + isc_sockaddr_t addr; + struct in_addr in; + struct in6_addr in6; + unsigned int h1, h2, h3, h4; + int ret; + + UNUSED(state); + + in.s_addr = inet_addr("127.0.0.1"); + isc_sockaddr_fromin(&addr, &in, 1); + h1 = isc_sockaddr_hash(&addr, true); + h2 = isc_sockaddr_hash(&addr, false); + assert_int_not_equal(h1, h2); + + ret = inet_pton(AF_INET6, "::ffff:127.0.0.1", &in6); + assert_int_equal(ret, 1); + isc_sockaddr_fromin6(&addr, &in6, 1); + h3 = isc_sockaddr_hash(&addr, true); + h4 = isc_sockaddr_hash(&addr, false); + assert_int_equal(h1, h3); + assert_int_equal(h2, h4); +} + +/* test isc_sockaddr_isnetzero() */ +ISC_RUN_TEST_IMPL(sockaddr_isnetzero) { + isc_sockaddr_t addr; + struct in_addr in; + struct in6_addr in6; + bool r; + + size_t i; + struct { + const char *string; + bool expect; + } data4[] = { + { "0.0.0.0", true }, { "0.0.0.1", true }, + { "0.0.1.0", true }, { "0.1.0.0", true }, + { "1.0.0.0", false }, { "0.0.0.127", true }, + { "0.0.0.255", true }, { "127.0.0.1", false }, + { "255.255.255.255", false }, + }; + /* + * Mapped addresses are currently not netzero. + */ + struct { + const char *string; + bool expect; + } data6[] = { + { "::ffff:0.0.0.0", false }, + { "::ffff:0.0.0.1", false }, + { "::ffff:0.0.0.127", false }, + { "::ffff:0.0.0.255", false }, + { "::ffff:127.0.0.1", false }, + { "::ffff:255.255.255.255", false }, + }; + + UNUSED(state); + + for (i = 0; i < sizeof(data4) / sizeof(data4[0]); i++) { + in.s_addr = inet_addr(data4[i].string); + isc_sockaddr_fromin(&addr, &in, 1); + r = isc_sockaddr_isnetzero(&addr); + assert_int_equal(r, data4[i].expect); + } + + for (i = 0; i < sizeof(data6) / sizeof(data6[0]); i++) { + int ret = inet_pton(AF_INET6, data6[i].string, &in6); + assert_int_equal(ret, 1); + isc_sockaddr_fromin6(&addr, &in6, 1); + r = isc_sockaddr_isnetzero(&addr); + assert_int_equal(r, data6[i].expect); + } +} + +/* + * test that isc_sockaddr_eqaddrprefix() returns true when prefixes of a + * and b are equal, and false when they are not equal + */ +ISC_RUN_TEST_IMPL(sockaddr_eqaddrprefix) { + struct in_addr ina_a; + struct in_addr ina_b; + struct in_addr ina_c; + isc_sockaddr_t isa_a; + isc_sockaddr_t isa_b; + isc_sockaddr_t isa_c; + + UNUSED(state); + + assert_true(inet_pton(AF_INET, "194.100.32.87", &ina_a) >= 0); + assert_true(inet_pton(AF_INET, "194.100.32.80", &ina_b) >= 0); + assert_true(inet_pton(AF_INET, "194.101.32.87", &ina_c) >= 0); + + isc_sockaddr_fromin(&isa_a, &ina_a, 0); + isc_sockaddr_fromin(&isa_b, &ina_b, 42); + isc_sockaddr_fromin(&isa_c, &ina_c, 0); + + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 0)); + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 29)); + assert_true(isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 8)); + + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 30)); + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 32)); + assert_false(isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 16)); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(sockaddr_hash) +ISC_TEST_ENTRY(sockaddr_isnetzero) +ISC_TEST_ENTRY(sockaddr_eqaddrprefix) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/stats_test.c b/tests/isc/stats_test.c new file mode 100644 index 0000000..a475323 --- /dev/null +++ b/tests/isc/stats_test.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/stats.h> +#include <isc/util.h> + +#include <tests/isc.h> + +/* test stats */ +ISC_RUN_TEST_IMPL(isc_stats_basic) { + isc_stats_t *stats = NULL; + isc_result_t result; + + UNUSED(state); + + result = isc_stats_create(mctx, &stats, 4); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_stats_ncounters(stats), 4); + + /* Default all 0. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + assert_int_equal(isc_stats_get_counter(stats, i), 0); + } + + /* Test increment. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_increment(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 1); + isc_stats_increment(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 2); + } + + /* Test decrement. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_decrement(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 1); + isc_stats_decrement(stats, i); + assert_int_equal(isc_stats_get_counter(stats, i), 0); + } + + /* Test set. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_set(stats, i, i); + assert_int_equal(isc_stats_get_counter(stats, i), i); + } + + /* Test update if greater. */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + isc_stats_update_if_greater(stats, i, i); + assert_int_equal(isc_stats_get_counter(stats, i), i); + isc_stats_update_if_greater(stats, i, i + 1); + assert_int_equal(isc_stats_get_counter(stats, i), i + 1); + } + + /* Test resize. */ + isc_stats_resize(&stats, 3); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 4); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 5); + assert_int_equal(isc_stats_ncounters(stats), 5); + + /* Existing counters are retained */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + uint32_t expect = i + 1; + if (i == 4) { + expect = 0; + } + assert_int_equal(isc_stats_get_counter(stats, i), expect); + } + + isc_stats_detach(&stats); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_stats_basic) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/symtab_test.c b/tests/isc/symtab_test.c new file mode 100644 index 0000000..795a455 --- /dev/null +++ b/tests/isc/symtab_test.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/print.h> +#include <isc/symtab.h> +#include <isc/util.h> + +#include <tests/isc.h> + +static void +undefine(char *key, unsigned int type, isc_symvalue_t value, void *arg) { + UNUSED(arg); + + assert_int_equal(type, 1); + isc_mem_free(mctx, key); + isc_mem_free(mctx, value.as_pointer); +} + +/* test symbol table growth */ +ISC_RUN_TEST_IMPL(symtab_grow) { + isc_result_t result; + isc_symtab_t *st = NULL; + isc_symvalue_t value; + isc_symexists_t policy = isc_symexists_reject; + int i; + + UNUSED(state); + + result = isc_symtab_create(mctx, 3, undefine, NULL, false, &st); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(st); + + /* Nothing should be in the table yet */ + + /* + * Put 1024 entries in the table (this should necessate + * regrowing the hash table several times + */ + for (i = 0; i < 1024; i++) { + char str[16], *key; + + snprintf(str, sizeof(str), "%04x", i); + key = isc_mem_strdup(mctx, str); + assert_non_null(key); + value.as_pointer = isc_mem_strdup(mctx, str); + assert_non_null(value.as_pointer); + result = isc_symtab_define(st, key, 1, value, policy); + assert_int_equal(result, ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) { + undefine(key, 1, value, NULL); + } + } + + /* + * Try to put them in again; this should fail + */ + for (i = 0; i < 1024; i++) { + char str[16], *key; + + snprintf(str, sizeof(str), "%04x", i); + key = isc_mem_strdup(mctx, str); + assert_non_null(key); + value.as_pointer = isc_mem_strdup(mctx, str); + assert_non_null(value.as_pointer); + result = isc_symtab_define(st, key, 1, value, policy); + assert_int_equal(result, ISC_R_EXISTS); + undefine(key, 1, value, NULL); + } + + /* + * Retrieve them; this should succeed + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_lookup(st, str, 0, &value); + assert_int_equal(result, ISC_R_SUCCESS); + assert_string_equal(str, (char *)value.as_pointer); + } + + /* + * Undefine them + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_undefine(st, str, 1); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* + * Retrieve them again; this should fail + */ + for (i = 0; i < 1024; i++) { + char str[16]; + + snprintf(str, sizeof(str), "%04x", i); + result = isc_symtab_lookup(st, str, 0, &value); + assert_int_equal(result, ISC_R_NOTFOUND); + } + + isc_symtab_destroy(&st); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(symtab_grow) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/task_test.c b/tests/isc/task_test.c new file mode 100644 index 0000000..973ecc9 --- /dev/null +++ b/tests/isc/task_test.c @@ -0,0 +1,1408 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING + +#include <cmocka.h> + +#include <isc/atomic.h> +#include <isc/cmocka.h> +#include <isc/commandline.h> +#include <isc/condition.h> +#include <isc/managers.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/time.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include "netmgr/uv-compat.h" + +#include <tests/isc.h> + +/* Set to true (or use -v option) for verbose output */ +static bool verbose = false; + +static isc_mutex_t lock; +static isc_condition_t cv; + +atomic_int_fast32_t counter; +static int active[10]; +static atomic_bool done; + +static int +_setup(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + workers = 0; + setup_managers(state); + + return (0); +} + +static int +_setup2(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + /* Two worker threads */ + workers = 2; + setup_managers(state); + + return (0); +} + +static int +_setup4(void **state) { + isc_mutex_init(&lock); + isc_condition_init(&cv); + + /* Four worker threads */ + workers = 4; + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + + isc_condition_destroy(&cv); + isc_mutex_destroy(&lock); + + return (0); +} + +static void +set(isc_task_t *task, isc_event_t *event) { + atomic_int_fast32_t *value = (atomic_int_fast32_t *)event->ev_arg; + + UNUSED(task); + + isc_event_free(&event); + atomic_store(value, atomic_fetch_add(&counter, 1)); +} + +#include <isc/thread.h> + +static void +set_and_drop(isc_task_t *task, isc_event_t *event) { + atomic_int_fast32_t *value = (atomic_int_fast32_t *)event->ev_arg; + + UNUSED(task); + + isc_event_free(&event); + LOCK(&lock); + atomic_store(value, atomic_fetch_add(&counter, 1)); + UNLOCK(&lock); +} + +/* Create a task */ +ISC_RUN_TEST_IMPL(create_task) { + isc_result_t result; + isc_task_t *task = NULL; + + UNUSED(state); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_destroy(&task); + assert_null(task); +} + +/* Process events */ +ISC_RUN_TEST_IMPL(all_events) { + isc_result_t result; + isc_task_t *task = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b; + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, 0); + atomic_init(&b, 0); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* First event */ + event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST, set, &a, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), 0); + isc_task_send(task, &event); + + event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST, set, &b, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), 0); + isc_task_send(task, &event); + + while ((atomic_load(&a) == 0 || atomic_load(&b) == 0) && i++ < 5000) { + uv_sleep(1); + } + + assert_int_not_equal(atomic_load(&a), 0); + assert_int_not_equal(atomic_load(&b), 0); + + isc_task_destroy(&task); + assert_null(task); +} + +/* Privileged events */ +ISC_RUN_TEST_IMPL(privileged_events) { + isc_result_t result; + isc_task_t *task1 = NULL, *task2 = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b, c, d, e; + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, -1); + atomic_init(&b, -1); + atomic_init(&c, -1); + atomic_init(&d, -1); + atomic_init(&e, -1); + + /* + * Pause the net/task manager so we can fill up the work + * queue without things happening while we do it. + */ + isc_nm_pause(netmgr); + isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task1, "privileged", NULL); + assert_false(isc_task_getprivilege(task1)); + isc_task_setprivilege(task1, true); + assert_true(isc_task_getprivilege(task1)); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task2, "normal", NULL); + assert_false(isc_task_getprivilege(task2)); + + /* First event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &a, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), -1); + isc_task_send(task1, &event); + + /* Second event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, set, &b, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), -1); + isc_task_send(task2, &event); + + /* Third event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &c, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&c), -1); + isc_task_send(task1, &event); + + /* Fourth event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, set, &d, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&d), -1); + isc_task_send(task1, &event); + + /* Fifth event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, set, &e, + sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&e), -1); + isc_task_send(task2, &event); + + isc_nm_resume(netmgr); + + /* We're waiting for *all* variables to be set */ + while ((atomic_load(&a) < 0 || atomic_load(&b) < 0 || + atomic_load(&c) < 0 || atomic_load(&d) < 0 || + atomic_load(&e) < 0) && + i++ < 5000) + { + isc_test_nap(1000); + } + + /* + * We can't guarantee what order the events fire, but + * we do know the privileged tasks that set a, c, and d + * would have fired first. + */ + assert_true(atomic_load(&a) <= 3); + assert_true(atomic_load(&c) <= 3); + assert_true(atomic_load(&d) <= 3); + + /* ...and the non-privileged tasks that set b and e, last */ + assert_true(atomic_load(&b) > 3); + assert_true(atomic_load(&e) > 3); + + assert_int_equal(atomic_load(&counter), 6); + + isc_task_setprivilege(task1, false); + assert_false(isc_task_getprivilege(task1)); + + isc_task_destroy(&task1); + assert_null(task1); + isc_task_destroy(&task2); + assert_null(task2); +} + +/* + * Edge case: this tests that the task manager behaves as expected when + * we explicitly set it into normal mode *while* running privileged. + */ +ISC_RUN_TEST_IMPL(privilege_drop) { + isc_result_t result; + isc_task_t *task1 = NULL, *task2 = NULL; + isc_event_t *event = NULL; + atomic_int_fast32_t a, b, c, d, e; /* non valid states */ + int i = 0; + + UNUSED(state); + + atomic_init(&counter, 1); + atomic_init(&a, -1); + atomic_init(&b, -1); + atomic_init(&c, -1); + atomic_init(&d, -1); + atomic_init(&e, -1); + + /* + * Pause the net/task manager so we can fill up the work queue + * without things happening while we do it. + */ + isc_nm_pause(netmgr); + isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task1, "privileged", NULL); + assert_false(isc_task_getprivilege(task1)); + isc_task_setprivilege(task1, true); + assert_true(isc_task_getprivilege(task1)); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + isc_task_setname(task2, "normal", NULL); + assert_false(isc_task_getprivilege(task2)); + + /* First event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &a, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&a), -1); + isc_task_send(task1, &event); + + /* Second event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, + set_and_drop, &b, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&b), -1); + isc_task_send(task2, &event); + + /* Third event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &c, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&c), -1); + isc_task_send(task1, &event); + + /* Fourth event: privileged */ + event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST, + set_and_drop, &d, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&d), -1); + isc_task_send(task1, &event); + + /* Fifth event: not privileged */ + event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST, + set_and_drop, &e, sizeof(isc_event_t)); + assert_non_null(event); + + assert_int_equal(atomic_load(&e), -1); + isc_task_send(task2, &event); + + isc_nm_resume(netmgr); + + /* We're waiting for all variables to be set. */ + while ((atomic_load(&a) == -1 || atomic_load(&b) == -1 || + atomic_load(&c) == -1 || atomic_load(&d) == -1 || + atomic_load(&e) == -1) && + i++ < 5000) + { + isc_test_nap(1000); + } + + /* + * We need to check that all privilege mode events were fired + * in privileged mode, and non privileged in non-privileged. + */ + assert_true(atomic_load(&a) <= 3); + assert_true(atomic_load(&c) <= 3); + assert_true(atomic_load(&d) <= 3); + + /* ...and neither of the non-privileged tasks did... */ + assert_true(atomic_load(&b) > 3); + assert_true(atomic_load(&e) > 3); + + /* ...but all five of them did run. */ + assert_int_equal(atomic_load(&counter), 6); + + isc_task_destroy(&task1); + assert_null(task1); + isc_task_destroy(&task2); + assert_null(task2); +} + +/* + * Basic task functions: + */ +static void +basic_cb(isc_task_t *task, isc_event_t *event) { + int i, j; + + UNUSED(task); + + j = 0; + for (i = 0; i < 1000000; i++) { + j += 100; + } + + UNUSED(j); + + if (verbose) { + print_message("# task %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static void +basic_shutdown(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (verbose) { + print_message("# shutdown %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static void +basic_tick(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (verbose) { + print_message("# %s\n", (char *)event->ev_arg); + } + + isc_event_free(&event); +} + +static char one[] = "1"; +static char two[] = "2"; +static char three[] = "3"; +static char four[] = "4"; +static char tick[] = "tick"; +static char tock[] = "tock"; + +ISC_RUN_TEST_IMPL(basic) { + isc_result_t result; + isc_task_t *task1 = NULL; + isc_task_t *task2 = NULL; + isc_task_t *task3 = NULL; + isc_task_t *task4 = NULL; + isc_event_t *event = NULL; + isc_timer_t *ti1 = NULL; + isc_timer_t *ti2 = NULL; + isc_time_t absolute; + isc_interval_t interval; + char *testarray[] = { one, one, one, one, one, one, one, one, + one, two, three, four, two, three, four, NULL }; + int i; + + UNUSED(state); + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task3); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_create(taskmgr, 0, &task4); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task1, basic_shutdown, one); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task2, basic_shutdown, two); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task3, basic_shutdown, three); + assert_int_equal(result, ISC_R_SUCCESS); + result = isc_task_onshutdown(task4, basic_shutdown, four); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_settoepoch(&absolute); + isc_interval_set(&interval, 1, 0); + result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute, + &interval, task1, basic_tick, tick, &ti1); + assert_int_equal(result, ISC_R_SUCCESS); + + ti2 = NULL; + isc_time_settoepoch(&absolute); + isc_interval_set(&interval, 1, 0); + result = isc_timer_create(timermgr, isc_timertype_ticker, &absolute, + &interval, task2, basic_tick, tock, &ti2); + assert_int_equal(result, ISC_R_SUCCESS); + + sleep(2); + + for (i = 0; testarray[i] != NULL; i++) { + /* + * Note: (void *)1 is used as a sender here, since some + * compilers don't like casting a function pointer to a + * (void *). + * + * In a real use, it is more likely the sender would be a + * structure (socket, timer, task, etc) but this is just a + * test program. + */ + event = isc_event_allocate(mctx, (void *)1, 1, basic_cb, + testarray[i], sizeof(*event)); + assert_non_null(event); + isc_task_send(task1, &event); + } + + (void)isc_task_purge(task3, NULL, 0, 0); + + isc_task_detach(&task1); + isc_task_detach(&task2); + isc_task_detach(&task3); + isc_task_detach(&task4); + + sleep(10); + isc_timer_destroy(&ti1); + isc_timer_destroy(&ti2); +} + +/* + * Exclusive mode test: + * When one task enters exclusive mode, all other active + * tasks complete first. + */ +static int +spin(int n) { + int i; + int r = 0; + for (i = 0; i < n; i++) { + r += i; + if (r > 1000000) { + r = 0; + } + } + return (r); +} + +static void +exclusive_cb(isc_task_t *task, isc_event_t *event) { + int taskno = *(int *)(event->ev_arg); + + if (verbose) { + print_message("# task enter %d\n", taskno); + } + + /* task chosen from the middle of the range */ + if (taskno == 6) { + isc_result_t result; + int i; + + result = isc_task_beginexclusive(task); + assert_int_equal(result, ISC_R_SUCCESS); + + for (i = 0; i < 10; i++) { + assert_int_equal(active[i], 0); + } + + isc_task_endexclusive(task); + atomic_store(&done, true); + } else { + active[taskno]++; + (void)spin(10000000); + active[taskno]--; + } + + if (verbose) { + print_message("# task exit %d\n", taskno); + } + + if (atomic_load(&done)) { + isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof(int)); + isc_event_free(&event); + atomic_fetch_sub(&counter, 1); + } else { + isc_task_send(task, &event); + } +} + +ISC_RUN_TEST_IMPL(task_exclusive) { + isc_task_t *tasks[10]; + isc_result_t result; + int i; + + UNUSED(state); + + atomic_init(&counter, 0); + + for (i = 0; i < 10; i++) { + isc_event_t *event = NULL; + int *v; + + tasks[i] = NULL; + + if (i == 6) { + /* task chosen from the middle of the range */ + result = isc_task_create_bound(taskmgr, 0, &tasks[i], + 0); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_taskmgr_setexcltask(taskmgr, tasks[6]); + } else { + result = isc_task_create(taskmgr, 0, &tasks[i]); + assert_int_equal(result, ISC_R_SUCCESS); + } + + v = isc_mem_get(mctx, sizeof *v); + assert_non_null(v); + + *v = i; + + event = isc_event_allocate(mctx, NULL, 1, exclusive_cb, v, + sizeof(*event)); + assert_non_null(event); + + isc_task_send(tasks[i], &event); + atomic_fetch_add(&counter, 1); + } + + for (i = 0; i < 10; i++) { + isc_task_detach(&tasks[i]); + } + + while (atomic_load(&counter) > 0) { + uv_sleep(1); + } +} + +/* + * Max tasks test: + * The task system can create and execute many tasks. Tests with 10000. + */ +static void +maxtask_shutdown(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + if (event->ev_arg != NULL) { + isc_task_destroy((isc_task_t **)&event->ev_arg); + } else { + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + } + + isc_event_free(&event); +} + +static void +maxtask_cb(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + + if (event->ev_arg != NULL) { + isc_task_t *newtask = NULL; + + event->ev_arg = (void *)(((uintptr_t)event->ev_arg) - 1); + + /* + * Create a new task and forward the message. + */ + result = isc_task_create(taskmgr, 0, &newtask); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(newtask, maxtask_shutdown, + (void *)task); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_send(newtask, &event); + } else if (task != NULL) { + isc_task_destroy(&task); + isc_event_free(&event); + } +} + +ISC_RUN_TEST_IMPL(manytasks) { + isc_event_t *event = NULL; + uintptr_t ntasks = 10000; + + UNUSED(state); + + if (verbose) { + print_message("# Testing with %lu tasks\n", + (unsigned long)ntasks); + } + + atomic_init(&done, false); + + event = isc_event_allocate(mctx, (void *)1, 1, maxtask_cb, + (void *)ntasks, sizeof(*event)); + assert_non_null(event); + + LOCK(&lock); + maxtask_cb(NULL, event); + while (!atomic_load(&done)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); +} + +/* + * Shutdown test: + * When isc_task_shutdown() is called, shutdown events are posted + * in LIFO order. + */ + +static int nevents = 0; +static int nsdevents = 0; +static int senders[4]; +atomic_bool ready, all_done; + +static void +sd_sde1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + assert_int_equal(nevents, 256); + assert_int_equal(nsdevents, 1); + ++nsdevents; + + if (verbose) { + print_message("# shutdown 1\n"); + } + + isc_event_free(&event); + + atomic_store(&all_done, true); +} + +static void +sd_sde2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + assert_int_equal(nevents, 256); + assert_int_equal(nsdevents, 0); + ++nsdevents; + + if (verbose) { + print_message("# shutdown 2\n"); + } + + isc_event_free(&event); +} + +static void +sd_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&ready)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + if (verbose) { + print_message("# event 1\n"); + } + + isc_event_free(&event); +} + +static void +sd_event2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + ++nevents; + + if (verbose) { + print_message("# event 2\n"); + } + + isc_event_free(&event); +} + +ISC_RUN_TEST_IMPL(task_shutdown) { + isc_result_t result; + isc_eventtype_t event_type; + isc_event_t *event = NULL; + isc_task_t *task = NULL; + int i; + + UNUSED(state); + + nevents = nsdevents = 0; + event_type = 3; + atomic_init(&ready, false); + atomic_init(&all_done, false); + + LOCK(&lock); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * This event causes the task to wait on cv. + */ + event = isc_event_allocate(mctx, &senders[1], event_type, sd_event1, + NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + + /* + * Now we fill up the task's event queue with some events. + */ + for (i = 0; i < 256; ++i) { + event = isc_event_allocate(mctx, &senders[1], event_type, + sd_event2, NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + } + + /* + * Now we register two shutdown events. + */ + result = isc_task_onshutdown(task, sd_sde1, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, sd_sde2, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_task_shutdown(task); + isc_task_detach(&task); + + /* + * Now we free the task by signaling cv. + */ + atomic_store(&ready, true); + SIGNAL(&cv); + UNLOCK(&lock); + + while (!atomic_load(&all_done)) { + isc_test_nap(1000); + } + + assert_int_equal(nsdevents, 2); +} + +/* + * Post-shutdown test: + * After isc_task_shutdown() has been called, any call to + * isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN. + */ +static void +psd_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + + while (!atomic_load(&done)) { + WAIT(&cv, &lock); + } + + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +psd_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + isc_event_free(&event); +} + +ISC_RUN_TEST_IMPL(post_shutdown) { + isc_result_t result; + isc_eventtype_t event_type; + isc_event_t *event; + isc_task_t *task; + + UNUSED(state); + + atomic_init(&done, false); + event_type = 4; + + isc_condition_init(&cv); + + LOCK(&lock); + + task = NULL; + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * This event causes the task to wait on cv. + */ + event = isc_event_allocate(mctx, &senders[1], event_type, psd_event1, + NULL, sizeof(*event)); + assert_non_null(event); + isc_task_send(task, &event); + + isc_task_shutdown(task); + + result = isc_task_onshutdown(task, psd_sde, NULL); + assert_int_equal(result, ISC_R_SHUTTINGDOWN); + + /* + * Release the task. + */ + atomic_store(&done, true); + + SIGNAL(&cv); + UNLOCK(&lock); + + isc_task_detach(&task); +} + +/* + * Helper for the purge tests below: + */ + +#define SENDERCNT 3 +#define TYPECNT 4 +#define TAGCNT 5 +#define NEVENTS (SENDERCNT * TYPECNT * TAGCNT) + +static bool testrange; +static void *purge_sender; +static isc_eventtype_t purge_type_first; +static isc_eventtype_t purge_type_last; +static void *purge_tag; +static int eventcnt; + +atomic_bool started; + +static void +pg_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&started)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +pg_event2(isc_task_t *task, isc_event_t *event) { + bool sender_match = false; + bool type_match = false; + bool tag_match = false; + + UNUSED(task); + + if ((purge_sender == NULL) || (purge_sender == event->ev_sender)) { + sender_match = true; + } + + if (testrange) { + if ((purge_type_first <= event->ev_type) && + (event->ev_type <= purge_type_last)) + { + type_match = true; + } + } else { + if (purge_type_first == event->ev_type) { + type_match = true; + } + } + + if ((purge_tag == NULL) || (purge_tag == event->ev_tag)) { + tag_match = true; + } + + if (sender_match && type_match && tag_match) { + if ((event->ev_attributes & ISC_EVENTATTR_NOPURGE) != 0) { + if (verbose) { + print_message("# event %p,%d,%p " + "matched but was not " + "purgeable\n", + event->ev_sender, + (int)event->ev_type, + event->ev_tag); + } + ++eventcnt; + } else if (verbose) { + print_message("# event %p,%d,%p not purged\n", + event->ev_sender, (int)event->ev_type, + event->ev_tag); + } + } else { + ++eventcnt; + } + + isc_event_free(&event); +} + +static void +pg_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +test_purge(int sender, int type, int tag, int exp_purged) { + isc_result_t result; + isc_task_t *task = NULL; + isc_event_t *eventtab[NEVENTS]; + isc_event_t *event = NULL; + isc_interval_t interval; + isc_time_t now; + int sender_cnt, type_cnt, tag_cnt, event_cnt, i; + int purged = 0; + + atomic_init(&started, false); + atomic_init(&done, false); + eventcnt = 0; + + isc_condition_init(&cv); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, pg_sde, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Block the task on cv. + */ + event = isc_event_allocate(mctx, (void *)1, 9999, pg_event1, NULL, + sizeof(*event)); + + assert_non_null(event); + isc_task_send(task, &event); + + /* + * Fill the task's queue with some messages with varying + * sender, type, tag, and purgeable attribute values. + */ + event_cnt = 0; + for (sender_cnt = 0; sender_cnt < SENDERCNT; ++sender_cnt) { + for (type_cnt = 0; type_cnt < TYPECNT; ++type_cnt) { + for (tag_cnt = 0; tag_cnt < TAGCNT; ++tag_cnt) { + eventtab[event_cnt] = isc_event_allocate( + mctx, &senders[sender + sender_cnt], + (isc_eventtype_t)(type + type_cnt), + pg_event2, NULL, sizeof(*event)); + + assert_non_null(eventtab[event_cnt]); + + eventtab[event_cnt]->ev_tag = + (void *)((uintptr_t)tag + tag_cnt); + + /* + * Mark events as non-purgeable if + * sender, type and tag are all + * odd-numbered. (There should be 4 + * of these out of 60 events total.) + */ + if (((sender_cnt % 2) != 0) && + ((type_cnt % 2) != 0) && + ((tag_cnt % 2) != 0)) + { + eventtab[event_cnt]->ev_attributes |= + ISC_EVENTATTR_NOPURGE; + } + ++event_cnt; + } + } + } + + for (i = 0; i < event_cnt; ++i) { + isc_task_send(task, &eventtab[i]); + } + + if (testrange) { + /* + * We're testing isc_task_purgerange. + */ + purged = isc_task_purgerange( + task, purge_sender, (isc_eventtype_t)purge_type_first, + (isc_eventtype_t)purge_type_last, purge_tag); + assert_int_equal(purged, exp_purged); + } else { + /* + * We're testing isc_task_purge. + */ + if (verbose) { + print_message("# purge events %p,%u,%p\n", purge_sender, + purge_type_first, purge_tag); + } + purged = isc_task_purge(task, purge_sender, + (isc_eventtype_t)purge_type_first, + purge_tag); + if (verbose) { + print_message("# purged %d expected %d\n", purged, + exp_purged); + } + + assert_int_equal(purged, exp_purged); + } + + /* + * Unblock the task, allowing event processing. + */ + LOCK(&lock); + atomic_store(&started, true); + SIGNAL(&cv); + + isc_task_shutdown(task); + + isc_interval_set(&interval, 5, 0); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&done)) { + result = isc_time_nowplusinterval(&now, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + WAITUNTIL(&cv, &lock, &now); + } + + UNLOCK(&lock); + + isc_task_detach(&task); + + assert_int_equal(eventcnt, event_cnt - exp_purged); +} + +/* + * Purge test: + * A call to isc_task_purge(task, sender, type, tag) purges all events of + * type 'type' and with tag 'tag' not marked as unpurgeable from sender + * from the task's " queue and returns the number of events purged. + */ +ISC_RUN_TEST_IMPL(purge) { + UNUSED(state); + + /* Try purging on a specific sender. */ + if (verbose) { + print_message("# testing purge on 2,4,8 expecting 1\n"); + } + purge_sender = &senders[2]; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 1); + + /* Try purging on all senders. */ + if (verbose) { + print_message("# testing purge on 0,4,8 expecting 3\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 3); + + /* Try purging on all senders, specified type, all tags. */ + if (verbose) { + print_message("# testing purge on 0,4,0 expecting 15\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 4; + purge_tag = NULL; + testrange = false; + test_purge(1, 4, 7, 15); + + /* Try purging on a specified tag, no such type. */ + if (verbose) { + print_message("# testing purge on 0,99,8 expecting 0\n"); + } + purge_sender = NULL; + purge_type_first = 99; + purge_type_last = 99; + purge_tag = (void *)8; + testrange = false; + test_purge(1, 4, 7, 0); + + /* Try purging on specified sender, type, all tags. */ + if (verbose) { + print_message("# testing purge on 3,5,0 expecting 5\n"); + } + purge_sender = &senders[3]; + purge_type_first = 5; + purge_type_last = 5; + purge_tag = NULL; + testrange = false; + test_purge(1, 4, 7, 5); +} + +/* + * Purge range test: + * A call to isc_event_purgerange(task, sender, first, last, tag) purges + * all events not marked unpurgeable from sender 'sender' and of type within + * the range 'first' to 'last' inclusive from the task's event queue and + * returns the number of tasks purged. + */ + +ISC_RUN_TEST_IMPL(purgerange) { + UNUSED(state); + + /* Now let's try some ranges. */ + /* testing purgerange on 2,4-5,8 expecting 1 */ + purge_sender = &senders[2]; + purge_type_first = 4; + purge_type_last = 5; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 1); + + /* Try purging on all senders. */ + if (verbose) { + print_message("# testing purge on 0,4-5,8 expecting 5\n"); + } + purge_sender = NULL; + purge_type_first = 4; + purge_type_last = 5; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 5); + + /* Try purging on all senders, specified type, all tags. */ + if (verbose) { + print_message("# testing purge on 0,5-6,0 expecting 28\n"); + } + purge_sender = NULL; + purge_type_first = 5; + purge_type_last = 6; + purge_tag = NULL; + testrange = true; + test_purge(1, 4, 7, 28); + + /* Try purging on a specified tag, no such type. */ + if (verbose) { + print_message("# testing purge on 0,99-101,8 expecting 0\n"); + } + purge_sender = NULL; + purge_type_first = 99; + purge_type_last = 101; + purge_tag = (void *)8; + testrange = true; + test_purge(1, 4, 7, 0); + + /* Try purging on specified sender, type, all tags. */ + if (verbose) { + print_message("# testing purge on 3,5-6,0 expecting 10\n"); + } + purge_sender = &senders[3]; + purge_type_first = 5; + purge_type_last = 6; + purge_tag = NULL; + testrange = true; + test_purge(1, 4, 7, 10); +} + +/* + * Helpers for purge event tests + */ +static void +pge_event1(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + while (!atomic_load(&started)) { + WAIT(&cv, &lock); + } + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +pge_event2(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + ++eventcnt; + isc_event_free(&event); +} + +static void +pge_sde(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + + LOCK(&lock); + atomic_store(&done, true); + SIGNAL(&cv); + UNLOCK(&lock); + + isc_event_free(&event); +} + +static void +try_purgeevent(bool purgeable) { + isc_result_t result; + isc_task_t *task = NULL; + bool purged; + isc_event_t *event1 = NULL; + isc_event_t *event2 = NULL; + isc_event_t *event2_clone = NULL; + isc_time_t now; + isc_interval_t interval; + + atomic_init(&started, false); + atomic_init(&done, false); + eventcnt = 0; + + isc_condition_init(&cv); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, pge_sde, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Block the task on cv. + */ + event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, + pge_event1, NULL, sizeof(*event1)); + assert_non_null(event1); + isc_task_send(task, &event1); + + event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, + pge_event2, NULL, sizeof(*event2)); + assert_non_null(event2); + + event2_clone = event2; + + if (purgeable) { + event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE; + } else { + event2->ev_attributes |= ISC_EVENTATTR_NOPURGE; + } + + isc_task_send(task, &event2); + + purged = isc_task_purgeevent(task, event2_clone); + assert_int_equal(purgeable, purged); + + /* + * Unblock the task, allowing event processing. + */ + LOCK(&lock); + atomic_store(&started, true); + SIGNAL(&cv); + + isc_task_shutdown(task); + + isc_interval_set(&interval, 5, 0); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&done)) { + result = isc_time_nowplusinterval(&now, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + WAITUNTIL(&cv, &lock, &now); + } + UNLOCK(&lock); + + isc_task_detach(&task); + + assert_int_equal(eventcnt, (purgeable ? 0 : 1)); +} + +/* + * Purge event test: + * When the event is marked as purgeable, a call to + * isc_task_purgeevent(task, event) purges the event 'event' from the + * task's queue and returns true. + */ + +ISC_RUN_TEST_IMPL(purgeevent) { + UNUSED(state); + + try_purgeevent(true); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(manytasks, _setup4, _teardown) +ISC_TEST_ENTRY_CUSTOM(all_events, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(basic, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(create_task, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(post_shutdown, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(privilege_drop, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(privileged_events, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(purge, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(purgeevent, _setup2, _teardown) +ISC_TEST_ENTRY_CUSTOM(task_shutdown, _setup4, _teardown) +ISC_TEST_ENTRY_CUSTOM(task_exclusive, _setup4, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/taskpool_test.c b/tests/isc/taskpool_test.c new file mode 100644 index 0000000..a92e0ad --- /dev/null +++ b/tests/isc/taskpool_test.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/task.h> +#include <isc/taskpool.h> +#include <isc/util.h> + +#include <tests/isc.h> + +#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K') +#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC) + +/* Create a taskpool */ +ISC_RUN_TEST_IMPL(create_pool) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 8, 2, false, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 8); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +/* Resize a taskpool */ +ISC_RUN_TEST_IMPL(expand_pool) { + isc_result_t result; + isc_taskpool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 10, 2, false, &pool1); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool1), 10); + + /* resizing to a smaller size should have no effect */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 5, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to the same size should have no effect */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 10, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 10); + assert_ptr_equal(pool2, hold); + assert_null(pool1); + pool1 = pool2; + pool2 = NULL; + + /* resizing to larger size should make a new pool */ + hold = pool1; + result = isc_taskpool_expand(&pool1, 20, false, &pool2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool2), 20); + assert_ptr_not_equal(pool2, hold); + assert_null(pool1); + + isc_taskpool_destroy(&pool2); + assert_null(pool2); +} + +/* Get tasks */ +ISC_RUN_TEST_IMPL(get_tasks) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 2, 2, false, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 2); + + /* two tasks in pool; make sure we can access them more than twice */ + isc_taskpool_gettask(pool, &task1); + assert_true(VALID_TASK(task1)); + + isc_taskpool_gettask(pool, &task2); + assert_true(VALID_TASK(task2)); + + isc_taskpool_gettask(pool, &task3); + assert_true(VALID_TASK(task3)); + + isc_task_destroy(&task1); + isc_task_destroy(&task2); + isc_task_destroy(&task3); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +/* Set privileges */ +ISC_RUN_TEST_IMPL(set_privilege) { + isc_result_t result; + isc_taskpool_t *pool = NULL; + isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; + + UNUSED(state); + + result = isc_taskpool_create(taskmgr, mctx, 2, 2, true, &pool); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_taskpool_size(pool), 2); + + isc_taskpool_gettask(pool, &task1); + isc_taskpool_gettask(pool, &task2); + isc_taskpool_gettask(pool, &task3); + + assert_true(VALID_TASK(task1)); + assert_true(VALID_TASK(task2)); + assert_true(VALID_TASK(task3)); + + assert_true(isc_task_getprivilege(task1)); + assert_true(isc_task_getprivilege(task2)); + assert_true(isc_task_getprivilege(task3)); + + isc_task_destroy(&task1); + isc_task_destroy(&task2); + isc_task_destroy(&task3); + + isc_taskpool_destroy(&pool); + assert_null(pool); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(create_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(expand_pool, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(get_tasks, setup_managers, teardown_managers) +ISC_TEST_ENTRY_CUSTOM(set_privilege, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/testdata/file/keep b/tests/isc/testdata/file/keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/isc/testdata/file/keep diff --git a/tests/isc/time_test.c b/tests/isc/time_test.c new file mode 100644 index 0000000..6b0f329 --- /dev/null +++ b/tests/isc/time_test.c @@ -0,0 +1,418 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/result.h> +#include <isc/time.h> +#include <isc/util.h> + +#include "time.c" + +#include <tests/isc.h> + +#define MAX_NS (NS_PER_SEC - 1) + +struct time_vectors { + isc_time_t a; + isc_interval_t b; + isc_time_t r; + isc_result_t result; +}; + +const struct time_vectors vectors_add[8] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS }, + { { 0, MAX_NS }, { 0, MAX_NS }, { 1, MAX_NS - 1 }, ISC_R_SUCCESS }, + { { 0, NS_PER_SEC / 2 }, + { 0, NS_PER_SEC / 2 }, + { 1, 0 }, + ISC_R_SUCCESS }, + { { UINT_MAX, MAX_NS }, { 0, 0 }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS }, + { { UINT_MAX, 0 }, { 0, MAX_NS }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS }, + { { UINT_MAX, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE }, + { { UINT_MAX, MAX_NS }, { 0, 1 }, { 0, 0 }, ISC_R_RANGE }, + { { UINT_MAX / 2 + 1, NS_PER_SEC / 2 }, + { UINT_MAX / 2, NS_PER_SEC / 2 }, + { 0, 0 }, + ISC_R_RANGE }, +}; + +const struct time_vectors vectors_sub[7] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS }, + { { 1, 0 }, { 0, MAX_NS }, { 0, 1 }, ISC_R_SUCCESS }, + { { 1, NS_PER_SEC / 2 }, + { 0, MAX_NS }, + { 0, NS_PER_SEC / 2 + 1 }, + ISC_R_SUCCESS }, + { { UINT_MAX, MAX_NS }, { UINT_MAX, 0 }, { 0, MAX_NS }, ISC_R_SUCCESS }, + { { 0, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE }, + { { 0, 0 }, { 0, MAX_NS }, { 0, 0 }, ISC_R_RANGE }, +}; + +ISC_RUN_TEST_IMPL(isc_time_add_test) { + UNUSED(state); + + for (size_t i = 0; i < ARRAY_SIZE(vectors_add); i++) { + isc_time_t r = { UINT_MAX, UINT_MAX }; + isc_result_t result = isc_time_add(&(vectors_add[i].a), + &(vectors_add[i].b), &r); + assert_int_equal(result, vectors_add[i].result); + if (result != ISC_R_SUCCESS) { + continue; + } + + assert_int_equal(r.seconds, vectors_add[i].r.seconds); + assert_int_equal(r.nanoseconds, vectors_add[i].r.nanoseconds); + } + + expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, MAX_NS + 1 }, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 }, + &(isc_time_t){ 0, 0 })); + + expect_assert_failure((void)isc_time_add((isc_time_t *)NULL, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, 0 }, + (isc_interval_t *)NULL, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_add( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL)); +} + +ISC_RUN_TEST_IMPL(isc_time_sub_test) { + UNUSED(state); + + for (size_t i = 0; i < ARRAY_SIZE(vectors_sub); i++) { + isc_time_t r = { UINT_MAX, UINT_MAX }; + isc_result_t result = isc_time_subtract( + &(vectors_sub[i].a), &(vectors_sub[i].b), &r); + assert_int_equal(result, vectors_sub[i].result); + if (result != ISC_R_SUCCESS) { + continue; + } + assert_int_equal(r.seconds, vectors_sub[i].r.seconds); + assert_int_equal(r.nanoseconds, vectors_sub[i].r.nanoseconds); + } + + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, MAX_NS + 1 }, &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 }, + &(isc_time_t){ 0, 0 })); + + expect_assert_failure((void)isc_time_subtract((isc_time_t *)NULL, + &(isc_interval_t){ 0, 0 }, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract(&(isc_time_t){ 0, 0 }, + (isc_interval_t *)NULL, + &(isc_time_t){ 0, 0 })); + expect_assert_failure((void)isc_time_subtract( + &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL)); +} + +/* parse http time stamp */ + +ISC_RUN_TEST_IMPL(isc_time_parsehttptimestamp_test) { + isc_result_t result; + isc_time_t t, x; + char buf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_formathttptimestamp(&t, buf, sizeof(buf)); + result = isc_time_parsehttptimestamp(buf, &x); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(isc_time_seconds(&t), isc_time_seconds(&x)); +} + +/* print UTC in ISO8601 */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 20); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40Z"); +} + +/* print UTC in ISO8601 with milliseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601ms_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.sssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 24); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + assert_int_equal(buf[23], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00.000Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601ms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40.123Z"); +} + +/* print UTC in ISO8601 with microseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601us_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now_hires(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 27); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + assert_int_equal(buf[26], 'Z'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1970-01-01T00:00:00.000000Z"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601us(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T09:46:40.123456Z"); +} + +/* print local time in ISO8601 */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601L_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 19); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601L(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40"); +} + +/* print local time in ISO8601 with milliseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lms_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.sss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 23); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00.000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40.123"); +} + +/* print local time in ISO8601 with microseconds */ + +ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lus_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now_hires(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 26); + assert_int_equal(buf[4], '-'); + assert_int_equal(buf[7], '-'); + assert_int_equal(buf[10], 'T'); + assert_int_equal(buf[13], ':'); + assert_int_equal(buf[16], ':'); + assert_int_equal(buf[19], '.'); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "1969-12-31T16:00:00.000000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123456000); + isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); + assert_string_equal(buf, "2015-12-13T01:46:40.123456"); +} + +/* print UTC time as yyyymmddhhmmsssss */ + +ISC_RUN_TEST_IMPL(isc_time_formatshorttimestamp_test) { + isc_result_t result; + isc_time_t t; + char buf[64]; + + UNUSED(state); + + setenv("TZ", "America/Los_Angeles", 1); + result = isc_time_now(&t); + assert_int_equal(result, ISC_R_SUCCESS); + + /* check formatting: yyyymmddhhmmsssss */ + memset(buf, 'X', sizeof(buf)); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_int_equal(strlen(buf), 17); + + /* check time conversion correctness */ + memset(buf, 'X', sizeof(buf)); + isc_time_settoepoch(&t); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_string_equal(buf, "19700101000000000"); + + memset(buf, 'X', sizeof(buf)); + isc_time_set(&t, 1450000000, 123000000); + isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); + assert_string_equal(buf, "20151213094640123"); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(isc_time_add_test) +ISC_TEST_ENTRY(isc_time_sub_test) +ISC_TEST_ENTRY(isc_time_parsehttptimestamp_test) +ISC_TEST_ENTRY(isc_time_formatISO8601_test) +ISC_TEST_ENTRY(isc_time_formatISO8601ms_test) +ISC_TEST_ENTRY(isc_time_formatISO8601us_test) +ISC_TEST_ENTRY(isc_time_formatISO8601L_test) +ISC_TEST_ENTRY(isc_time_formatISO8601Lms_test) +ISC_TEST_ENTRY(isc_time_formatISO8601Lus_test) +ISC_TEST_ENTRY(isc_time_formatshorttimestamp_test) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/timer_test.c b/tests/isc/timer_test.c new file mode 100644 index 0000000..644018a --- /dev/null +++ b/tests/isc/timer_test.c @@ -0,0 +1,599 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/atomic.h> +#include <isc/commandline.h> +#include <isc/condition.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/time.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include "netmgr/uv-compat.h" +#include "timer.c" + +#include <tests/isc.h> + +/* Set to true (or use -v option) for verbose output */ +static bool verbose = false; + +#define FUDGE_SECONDS 0 /* in absence of clock_getres() */ +#define FUDGE_NANOSECONDS 500000000 /* in absence of clock_getres() */ + +static isc_timer_t *timer = NULL; +static isc_condition_t cv; +static isc_mutex_t mx; +static isc_time_t endtime; +static isc_mutex_t lasttime_mx; +static isc_time_t lasttime; +static int seconds; +static int nanoseconds; +static atomic_int_fast32_t eventcnt; +static atomic_uint_fast32_t errcnt; +static int nevents; + +static int +_setup(void **state) { + atomic_init(&errcnt, ISC_R_SUCCESS); + + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + + return (0); +} + +static void +test_shutdown(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + + UNUSED(task); + + /* + * Signal shutdown processing complete. + */ + result = isc_mutex_lock(&mx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_condition_signal(&cv); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_mutex_unlock(&mx); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_event_free(&event); +} + +static void +setup_test(isc_timertype_t timertype, isc_time_t *expires, + isc_interval_t *interval, + void (*action)(isc_task_t *, isc_event_t *)) { + isc_result_t result; + isc_task_t *task = NULL; + isc_time_settoepoch(&endtime); + atomic_init(&eventcnt, 0); + + isc_mutex_init(&mx); + isc_mutex_init(&lasttime_mx); + + isc_condition_init(&cv); + + atomic_store(&errcnt, ISC_R_SUCCESS); + + LOCK(&mx); + + result = isc_task_create(taskmgr, 0, &task); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task, test_shutdown, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_mutex_lock(&lasttime_mx); + result = isc_time_now(&lasttime); + isc_mutex_unlock(&lasttime_mx); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_timer_create(timermgr, timertype, expires, interval, task, + action, (void *)timertype, &timer); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Wait for shutdown processing to complete. + */ + while (atomic_load(&eventcnt) != nevents) { + result = isc_condition_wait(&cv, &mx); + assert_int_equal(result, ISC_R_SUCCESS); + } + + UNLOCK(&mx); + + assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS); + + isc_task_detach(&task); + isc_mutex_destroy(&mx); + isc_mutex_destroy(&lasttime_mx); + (void)isc_condition_destroy(&cv); +} + +static void +set_global_error(isc_result_t result) { + (void)atomic_compare_exchange_strong( + &errcnt, &(uint_fast32_t){ ISC_R_SUCCESS }, result); +} + +static void +subthread_assert_true(bool expected, const char *file, unsigned int line) { + if (!expected) { + printf("# %s:%u subthread_assert_true\n", file, line); + set_global_error(ISC_R_UNEXPECTED); + } +} +#define subthread_assert_true(expected) \ + subthread_assert_true(expected, __FILE__, __LINE__) + +static void +subthread_assert_int_equal(int observed, int expected, const char *file, + unsigned int line) { + if (observed != expected) { + printf("# %s:%u subthread_assert_int_equal(%d != %d)\n", file, + line, observed, expected); + set_global_error(ISC_R_UNEXPECTED); + } +} +#define subthread_assert_int_equal(observed, expected) \ + subthread_assert_int_equal(observed, expected, __FILE__, __LINE__) + +static void +subthread_assert_result_equal(isc_result_t result, isc_result_t expected, + const char *file, unsigned int line) { + if (result != expected) { + printf("# %s:%u subthread_assert_result_equal(%u != %u)\n", + file, line, (unsigned int)result, + (unsigned int)expected); + set_global_error(result); + } +} +#define subthread_assert_result_equal(observed, expected) \ + subthread_assert_result_equal(observed, expected, __FILE__, __LINE__) + +static void +ticktock(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_interval_t interval; + isc_eventtype_t expected_event_type; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + expected_event_type = ISC_TIMEREVENT_LIFE; + if ((uintptr_t)event->ev_arg == isc_timertype_ticker) { + expected_event_type = ISC_TIMEREVENT_TICK; + } + + if (event->ev_type != expected_event_type) { + print_error("# expected event type %u, got %u\n", + expected_event_type, event->ev_type); + } + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_event_free(&event); + + if (atomic_load(&eventcnt) == nevents) { + result = isc_time_now(&endtime); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + isc_timer_destroy(&timer); + isc_task_shutdown(task); + } +} + +/* + * Individual unit tests + */ + +/* timer type ticker */ +ISC_RUN_TEST_IMPL(ticker) { + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 12; + seconds = 0; + nanoseconds = 500000000; + + isc_interval_set(&interval, seconds, nanoseconds); + isc_time_settoepoch(&expires); + + setup_test(isc_timertype_ticker, &expires, &interval, ticktock); +} + +/* timer type once reaches lifetime */ +ISC_RUN_TEST_IMPL(once_life) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 1; + seconds = 1; + nanoseconds = 100000000; + + isc_interval_set(&interval, seconds, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + + setup_test(isc_timertype_once, &expires, &interval, ticktock); +} + +static void +test_idle(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_interval_t interval; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_IDLE); + + isc_event_free(&event); + + isc_timer_destroy(&timer); + isc_task_shutdown(task); +} + +/* timer type once idles out */ +ISC_RUN_TEST_IMPL(once_idle) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 1; + seconds = 1; + nanoseconds = 200000000; + + isc_interval_set(&interval, seconds + 1, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + + setup_test(isc_timertype_once, &expires, &interval, test_idle); +} + +/* timer reset */ +static void +test_reset(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t now; + isc_time_t base; + isc_time_t ulim; + isc_time_t llim; + isc_time_t expires; + isc_interval_t interval; + + int tick = atomic_fetch_add(&eventcnt, 1); + + if (verbose) { + print_message("# tick %d\n", tick); + } + + /* + * Check expired time. + */ + + result = isc_time_now(&now); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, seconds, nanoseconds); + isc_mutex_lock(&lasttime_mx); + result = isc_time_add(&lasttime, &interval, &base); + isc_mutex_unlock(&lasttime_mx); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, FUDGE_SECONDS, FUDGE_NANOSECONDS); + result = isc_time_add(&base, &interval, &ulim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + result = isc_time_subtract(&base, &interval, &llim); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + subthread_assert_true(isc_time_compare(&llim, &now) <= 0); + subthread_assert_true(isc_time_compare(&ulim, &now) >= 0); + + isc_interval_set(&interval, 0, 0); + isc_mutex_lock(&lasttime_mx); + isc_time_add(&now, &interval, &lasttime); + isc_mutex_unlock(&lasttime_mx); + + int _eventcnt = atomic_load(&eventcnt); + + if (_eventcnt < 3) { + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_TICK); + + if (_eventcnt == 2) { + isc_interval_set(&interval, seconds, nanoseconds); + result = isc_time_nowplusinterval(&expires, &interval); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + result = isc_timer_reset(timer, isc_timertype_once, + &expires, &interval, false); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + } + + isc_event_free(&event); + } else { + subthread_assert_int_equal(event->ev_type, ISC_TIMEREVENT_LIFE); + + isc_event_free(&event); + isc_timer_destroy(&timer); + isc_task_shutdown(task); + } +} + +ISC_RUN_TEST_IMPL(reset) { + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + nevents = 3; + seconds = 0; + nanoseconds = 750000000; + + isc_interval_set(&interval, seconds, nanoseconds); + isc_time_settoepoch(&expires); + + setup_test(isc_timertype_ticker, &expires, &interval, test_reset); +} + +static atomic_bool startflag; +static atomic_bool shutdownflag; +static isc_timer_t *tickertimer = NULL; +static isc_timer_t *oncetimer = NULL; +static isc_task_t *task1 = NULL; +static isc_task_t *task2 = NULL; + +/* + * task1 blocks on mx while events accumulate + * in its queue, until signaled by task2. + */ + +static void +tick_event(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(task); + + if (!atomic_load(&startflag)) { + if (verbose) { + print_message("# tick_event %d\n", -1); + } + isc_event_free(&event); + return; + } + + int tick = atomic_fetch_add(&eventcnt, 1); + if (verbose) { + print_message("# tick_event %d\n", tick); + } + + /* + * On the first tick, purge all remaining tick events + * and then shut down the task. + */ + if (tick == 0) { + isc_time_settoepoch(&expires); + isc_interval_set(&interval, seconds, 0); + result = isc_timer_reset(tickertimer, isc_timertype_ticker, + &expires, &interval, true); + subthread_assert_result_equal(result, ISC_R_SUCCESS); + + isc_task_shutdown(task); + } + + isc_event_free(&event); +} + +static void +once_event(isc_task_t *task, isc_event_t *event) { + if (verbose) { + print_message("# once_event\n"); + } + + /* + * Allow task1 to start processing events. + */ + atomic_store(&startflag, true); + + isc_event_free(&event); + isc_task_shutdown(task); +} + +static void +shutdown_purge(isc_task_t *task, isc_event_t *event) { + UNUSED(task); + UNUSED(event); + + if (verbose) { + print_message("# shutdown_event\n"); + } + + /* + * Signal shutdown processing complete. + */ + atomic_store(&shutdownflag, 1); + + isc_event_free(&event); +} + +/* timer events purged */ +ISC_RUN_TEST_IMPL(purge) { + isc_result_t result; + isc_time_t expires; + isc_interval_t interval; + + UNUSED(state); + + atomic_init(&startflag, 0); + atomic_init(&shutdownflag, 0); + atomic_init(&eventcnt, 0); + seconds = 1; + nanoseconds = 0; + + result = isc_task_create(taskmgr, 0, &task1); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_onshutdown(task1, shutdown_purge, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + result = isc_task_create(taskmgr, 0, &task2); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_time_settoepoch(&expires); + isc_interval_set(&interval, seconds, 0); + + tickertimer = NULL; + result = isc_timer_create(timermgr, isc_timertype_ticker, &expires, + &interval, task1, tick_event, NULL, + &tickertimer); + assert_int_equal(result, ISC_R_SUCCESS); + + oncetimer = NULL; + + isc_interval_set(&interval, (seconds * 2) + 1, 0); + result = isc_time_nowplusinterval(&expires, &interval); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_interval_set(&interval, 0, 0); + result = isc_timer_create(timermgr, isc_timertype_once, &expires, + &interval, task2, once_event, NULL, + &oncetimer); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Wait for shutdown processing to complete. + */ + while (!atomic_load(&shutdownflag)) { + uv_sleep(1); + } + + assert_int_equal(atomic_load(&errcnt), ISC_R_SUCCESS); + + assert_int_equal(atomic_load(&eventcnt), 1); + + isc_timer_destroy(&tickertimer); + isc_timer_destroy(&oncetimer); + isc_task_destroy(&task1); + isc_task_destroy(&task2); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(ticker, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(once_life, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(once_idle, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(reset, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(purge, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/isc/uv_wrap.h b/tests/isc/uv_wrap.h new file mode 100644 index 0000000..5c557b8 --- /dev/null +++ b/tests/isc/uv_wrap.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#if HAVE_CMOCKA +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <uv.h> + +#include <isc/atomic.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include "../netmgr/uv-compat.h" + +/* uv_udp_t */ + +int +__wrap_uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock); +int +__wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, + unsigned int flags); +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr); +int +__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name, + int *namelen); +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ +int +__wrap_uv_udp_getsockname(const uv_udp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_udp_send(uv_udp_send_t *req, uv_udp_t *handle, const uv_buf_t bufs[], + unsigned int nbufs, const struct sockaddr *addr, + uv_udp_send_cb send_cb); +int +__wrap_uv_udp_recv_start(uv_udp_t *handle, uv_alloc_cb alloc_cb, + uv_udp_recv_cb recv_cb); +int +__wrap_uv_udp_recv_stop(uv_udp_t *handle); + +/* uv_tcp_t */ +int +__wrap_uv_tcp_open(uv_tcp_t *handle, uv_os_sock_t sock); +int +__wrap_uv_tcp_bind(uv_tcp_t *handle, const struct sockaddr *addr, + unsigned int flags); +int +__wrap_uv_tcp_getsockname(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_tcp_getpeername(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen); +int +__wrap_uv_tcp_connect(uv_connect_t *req, uv_tcp_t *handle, + const struct sockaddr *addr, uv_connect_cb cb); + +/* uv_stream_t */ +int +__wrap_uv_listen(uv_stream_t *stream, int backlog, uv_connection_cb cb); +int +__wrap_uv_accept(uv_stream_t *server, uv_stream_t *client); + +/* uv_handle_t */ +int +__wrap_uv_send_buffer_size(uv_handle_t *handle, int *value); +int +__wrap_uv_recv_buffer_size(uv_handle_t *handle, int *value); +int +__wrap_uv_fileno(const uv_handle_t *handle, uv_os_fd_t *fd); + +/* uv_timer_t */ +/* FIXME */ +/* + * uv_timer_init + * uv_timer_start + */ + +static atomic_int __state_uv_udp_open = 0; + +int +__wrap_uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock) { + if (atomic_load(&__state_uv_udp_open) == 0) { + return (uv_udp_open(handle, sock)); + } + return (atomic_load(&__state_uv_udp_open)); +} + +static atomic_int __state_uv_udp_bind = 0; + +int +__wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, + unsigned int flags) { + if (atomic_load(&__state_uv_udp_bind) == 0) { + return (uv_udp_bind(handle, addr, flags)); + } + return (atomic_load(&__state_uv_udp_bind)); +} + +static atomic_int __state_uv_udp_connect __attribute__((unused)) = 0; + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) { + if (atomic_load(&__state_uv_udp_connect) == 0) { + return (uv_udp_connect(handle, addr)); + } + return (atomic_load(&__state_uv_udp_connect)); +} +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ + +static atomic_int __state_uv_udp_getpeername __attribute__((unused)) = 0; + +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +int +__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_udp_getpeername) == 0) { + return (uv_udp_getpeername(handle, name, namelen)); + } + return (atomic_load(&__state_uv_udp_getpeername)); +} +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ + +static atomic_int __state_uv_udp_getsockname = 0; +int +__wrap_uv_udp_getsockname(const uv_udp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_udp_getsockname) == 0) { + return (uv_udp_getsockname(handle, name, namelen)); + } + return (atomic_load(&__state_uv_udp_getsockname)); +} + +static atomic_int __state_uv_udp_send = 0; +int +__wrap_uv_udp_send(uv_udp_send_t *req, uv_udp_t *handle, const uv_buf_t bufs[], + unsigned int nbufs, const struct sockaddr *addr, + uv_udp_send_cb send_cb) { + if (atomic_load(&__state_uv_udp_send) == 0) { + return (uv_udp_send(req, handle, bufs, nbufs, addr, send_cb)); + } + return (atomic_load(&__state_uv_udp_send)); +} + +static atomic_int __state_uv_udp_recv_start = 0; +int +__wrap_uv_udp_recv_start(uv_udp_t *handle, uv_alloc_cb alloc_cb, + uv_udp_recv_cb recv_cb) { + if (atomic_load(&__state_uv_udp_recv_start) == 0) { + return (uv_udp_recv_start(handle, alloc_cb, recv_cb)); + } + return (atomic_load(&__state_uv_udp_recv_start)); +} + +static atomic_int __state_uv_udp_recv_stop = 0; +int +__wrap_uv_udp_recv_stop(uv_udp_t *handle) { + if (atomic_load(&__state_uv_udp_recv_stop) == 0) { + return (uv_udp_recv_stop(handle)); + } + return (atomic_load(&__state_uv_udp_recv_stop)); +} + +static atomic_int __state_uv_tcp_open = 0; +int +__wrap_uv_tcp_open(uv_tcp_t *handle, uv_os_sock_t sock) { + if (atomic_load(&__state_uv_tcp_open) == 0) { + return (uv_tcp_open(handle, sock)); + } + return (atomic_load(&__state_uv_tcp_open)); +} + +static atomic_int __state_uv_tcp_bind = 0; +int +__wrap_uv_tcp_bind(uv_tcp_t *handle, const struct sockaddr *addr, + unsigned int flags) { + if (atomic_load(&__state_uv_tcp_bind) == 0) { + return (uv_tcp_bind(handle, addr, flags)); + } + return (atomic_load(&__state_uv_tcp_bind)); +} + +static atomic_int __state_uv_tcp_getsockname = 0; +int +__wrap_uv_tcp_getsockname(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_tcp_getsockname) == 0) { + return (uv_tcp_getsockname(handle, name, namelen)); + } + return (atomic_load(&__state_uv_tcp_getsockname)); +} + +static atomic_int __state_uv_tcp_getpeername = 0; +int +__wrap_uv_tcp_getpeername(const uv_tcp_t *handle, struct sockaddr *name, + int *namelen) { + if (atomic_load(&__state_uv_tcp_getpeername) == 0) { + return (uv_tcp_getpeername(handle, name, namelen)); + } + return (atomic_load(&__state_uv_tcp_getpeername)); +} + +static atomic_int __state_uv_tcp_connect = 0; +int +__wrap_uv_tcp_connect(uv_connect_t *req, uv_tcp_t *handle, + const struct sockaddr *addr, uv_connect_cb cb) { + if (atomic_load(&__state_uv_tcp_connect) == 0) { + return (uv_tcp_connect(req, handle, addr, cb)); + } + return (atomic_load(&__state_uv_tcp_connect)); +} + +static atomic_int __state_uv_listen = 0; +int +__wrap_uv_listen(uv_stream_t *stream, int backlog, uv_connection_cb cb) { + if (atomic_load(&__state_uv_listen) == 0) { + return (uv_listen(stream, backlog, cb)); + } + return (atomic_load(&__state_uv_listen)); +} + +static atomic_int __state_uv_accept = 0; +int +__wrap_uv_accept(uv_stream_t *server, uv_stream_t *client) { + if (atomic_load(&__state_uv_accept) == 0) { + return (uv_accept(server, client)); + } + return (atomic_load(&__state_uv_accept)); +} + +static atomic_int __state_uv_send_buffer_size = 0; +int +__wrap_uv_send_buffer_size(uv_handle_t *handle, int *value) { + if (atomic_load(&__state_uv_send_buffer_size) == 0) { + return (uv_send_buffer_size(handle, value)); + } + return (atomic_load(&__state_uv_send_buffer_size)); +} + +static atomic_int __state_uv_recv_buffer_size = 0; +int +__wrap_uv_recv_buffer_size(uv_handle_t *handle, int *value) { + if (atomic_load(&__state_uv_recv_buffer_size) == 0) { + return (uv_recv_buffer_size(handle, value)); + } + return (atomic_load(&__state_uv_recv_buffer_size)); +} + +static atomic_int __state_uv_fileno = 0; +int +__wrap_uv_fileno(const uv_handle_t *handle, uv_os_fd_t *fd) { + if (atomic_load(&__state_uv_fileno) == 0) { + return (uv_fileno(handle, fd)); + } + return (atomic_load(&__state_uv_fileno)); +} + +#define uv_udp_open(...) __wrap_uv_udp_open(__VA_ARGS__) +#define uv_udp_bind(...) __wrap_uv_udp_bind(__VA_ARGS__) +#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0) +#define uv_udp_connect(...) __wrap_uv_udp_connect(__VA_ARGS__) +#define uv_udp_getpeername(...) __wrap_uv_udp_getpeername(__VA_ARGS__) +#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */ +#define uv_udp_getsockname(...) __wrap_uv_udp_getsockname(__VA_ARGS__) +#define uv_udp_send(...) __wrap_uv_udp_send(__VA_ARGS__) +#define uv_udp_recv_start(...) __wrap_uv_udp_recv_start(__VA_ARGS__) +#define uv_udp_recv_stop(...) __wrap_uv_udp_recv_stop(__VA_ARGS__) + +#define uv_tcp_open(...) __wrap_uv_tcp_open(__VA_ARGS__) +#define uv_tcp_bind(...) __wrap_uv_tcp_bind(__VA_ARGS__) +#define uv_tcp_getsockname(...) __wrap_uv_tcp_getsockname(__VA_ARGS__) +#define uv_tcp_getpeername(...) __wrap_uv_tcp_getpeername(__VA_ARGS__) +#define uv_tcp_connect(...) __wrap_uv_tcp_connect(__VA_ARGS__) + +#define uv_listen(...) __wrap_uv_listen(__VA_ARGS__) +#define uv_accept(...) __wrap_uv_accept(__VA_ARGS__) + +#define uv_send_buffer_size(...) __wrap_uv_send_buffer_size(__VA_ARGS__) +#define uv_recv_buffer_size(...) __wrap_uv_recv_buffer_size(__VA_ARGS__) +#define uv_fileno(...) __wrap_uv_fileno(__VA_ARGS__) + +#define RESET_RETURN \ + { \ + atomic_store(&__state_uv_udp_open, 0); \ + atomic_store(&__state_uv_udp_bind, 0); \ + atomic_store(&__state_uv_udp_connect, 0); \ + atomic_store(&__state_uv_udp_getpeername, 0); \ + atomic_store(&__state_uv_udp_getsockname, 0); \ + atomic_store(&__state_uv_udp_send, 0); \ + atomic_store(&__state_uv_udp_recv_start, 0); \ + atomic_store(&__state_uv_udp_recv_stop, 0); \ + atomic_store(&__state_uv_tcp_open, 0); \ + atomic_store(&__state_uv_tcp_bind, 0); \ + atomic_store(&__state_uv_tcp_getpeername, 0); \ + atomic_store(&__state_uv_tcp_getsockname, 0); \ + atomic_store(&__state_uv_tcp_connect, 0); \ + atomic_store(&__state_uv_listen, 0); \ + atomic_store(&__state_uv_accept, 0); \ + atomic_store(&__state_uv_send_buffer_size, 0); \ + atomic_store(&__state_uv_recv_buffer_size, 0); \ + atomic_store(&__state_uv_fileno, 0); \ + } + +#define WILL_RETURN(func, value) atomic_store(&__state_##func, value) + +#endif /* HAVE_CMOCKA */ diff --git a/tests/isccfg/Makefile.am b/tests/isccfg/Makefile.am new file mode 100644 index 0000000..5a6fb03 --- /dev/null +++ b/tests/isccfg/Makefile.am @@ -0,0 +1,20 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(LIBUV_LIBS) + +check_PROGRAMS = \ + duration_test \ + parser_test + +include $(top_srcdir)/Makefile.tests diff --git a/tests/isccfg/Makefile.in b/tests/isccfg/Makefile.in new file mode 100644 index 0000000..712138a --- /dev/null +++ b/tests/isccfg/Makefile.in @@ -0,0 +1,1174 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = duration_test$(EXEEXT) parser_test$(EXEEXT) +subdir = tests/isccfg +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +duration_test_SOURCES = duration_test.c +duration_test_OBJECTS = duration_test.$(OBJEXT) +duration_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +duration_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +parser_test_SOURCES = parser_test.c +parser_test_OBJECTS = parser_test.$(OBJEXT) +parser_test_LDADD = $(LDADD) +parser_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/duration_test.Po \ + ./$(DEPDIR)/parser_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = duration_test.c parser_test.c +DIST_SOURCES = duration_test.c parser_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) $(LIBUV_CFLAGS) -I$(top_srcdir)/lib/isc \ + $(CMOCKA_CFLAGS) -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) $(LIBUV_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/isccfg/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/isccfg/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +duration_test$(EXEEXT): $(duration_test_OBJECTS) $(duration_test_DEPENDENCIES) $(EXTRA_duration_test_DEPENDENCIES) + @rm -f duration_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(duration_test_OBJECTS) $(duration_test_LDADD) $(LIBS) + +parser_test$(EXEEXT): $(parser_test_OBJECTS) $(parser_test_DEPENDENCIES) $(EXTRA_parser_test_DEPENDENCIES) + @rm -f parser_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(parser_test_OBJECTS) $(parser_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duration_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +duration_test.log: duration_test$(EXEEXT) + @p='duration_test$(EXEEXT)'; \ + b='duration_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +parser_test.log: parser_test$(EXEEXT) + @p='parser_test$(EXEEXT)'; \ + b='parser_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/duration_test.Po + -rm -f ./$(DEPDIR)/parser_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/duration_test.Po + -rm -f ./$(DEPDIR)/parser_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/isccfg/duration_test.c b/tests/isccfg/duration_test.c new file mode 100644 index 0000000..32028a5 --- /dev/null +++ b/tests/isccfg/duration_test.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/lex.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <isccfg/cfg.h> +#include <isccfg/grammar.h> +#include <isccfg/namedconf.h> + +#include <tests/isc.h> + +isc_log_t *lctx = NULL; +static isc_logcategory_t categories[] = { { "", 0 }, + { "client", 0 }, + { "network", 0 }, + { "update", 0 }, + { "queries", 0 }, + { "unmatched", 0 }, + { "update-security", 0 }, + { "query-errors", 0 }, + { NULL, 0 } }; + +ISC_SETUP_TEST_IMPL(group) { + isc_result_t result; + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + + isc_log_create(mctx, &lctx, &logconfig); + isc_log_registercategories(lctx, categories); + isc_log_setcontext(lctx); + + destination.file.stream = stderr; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, &destination, 0); + result = isc_log_usechannel(logconfig, "stderr", NULL, NULL); + + if (result != ISC_R_SUCCESS) { + return (-1); + } + + return (0); +} + +ISC_TEARDOWN_TEST_IMPL(group) { + if (lctx == NULL) { + return (-1); + } + + isc_log_setcontext(NULL); + isc_log_destroy(&lctx); + + return (0); +} + +struct duration_conf { + const char *string; + uint32_t time; + const char *out; +}; +typedef struct duration_conf duration_conf_t; + +static void +output(void *closure, const char *text, int textlen) { + int r; + + REQUIRE(textlen >= 0 && textlen < CFG_DURATION_MAXLEN); + + r = snprintf(closure, CFG_DURATION_MAXLEN, "%s", text); + INSIST(r == textlen); +} + +/* test cfg_obj_asduration() and cfg_print_duration() */ +ISC_RUN_TEST_IMPL(duration) { + isc_result_t result; + /* + * When 'out' is NULL, the printed result is expected to be the same as + * the input 'string', compared by ignoring the case of the characters. + */ + duration_conf_t durations[] = { + { .string = "unlimited", .time = 0 }, + { .string = "PT0S", .time = 0 }, + { .string = "PT42S", .time = 42 }, + { .string = "PT10m", .time = 600 }, + { .string = "PT10m4S", .time = 604 }, + { .string = "PT3600S", .time = 3600 }, + { .string = "pT2H", .time = 7200 }, + { .string = "Pt2H3S", .time = 7203 }, + { .string = "PT2h1m3s", .time = 7263 }, + { .string = "p7d", .time = 604800 }, + { .string = "P7DT2h", .time = 612000 }, + { .string = "P2W", .time = 1209600 }, + { .string = "P3M", .time = 8035200 }, + { .string = "P3MT10M", .time = 8035800 }, + { .string = "p5y", .time = 157680000 }, + { .string = "P5YT2H", .time = 157687200 }, + { .string = "P1Y1M1DT1H1M1S", .time = 34304461 }, + { .string = "P99Y399M999DT3999H9999M2911754S", + .time = UINT32_MAX - 1 }, + { .string = "P99Y399M999DT3999H9999M2911755S", + .time = UINT32_MAX }, + { .string = "P4294967295Y4294967295M4294967295D" + "T4294967295H4294967295M4294967295S", + .time = UINT32_MAX }, + { .string = "PT4294967294S", .time = UINT32_MAX - 1 }, + { .string = "PT4294967295S", .time = UINT32_MAX }, + { .string = "0", .time = 0 }, + { .string = "30", .time = 30 }, + { .string = "42s", .time = 42, .out = "42" }, + { .string = "10m", .time = 600, .out = "600" }, + { .string = "2H", .time = 7200, .out = "7200" }, + { .string = "7d", .time = 604800, .out = "604800" }, + { .string = "2w", .time = 1209600, .out = "1209600" }, + { 0 }, /* Indicates that the remaining durations are invalid. */ + { .string = "PT4Y" }, + { .string = "P-4Y2M" }, + { .string = "P5H1M30S" }, + { .string = "P7Y4W" }, + { .string = "X7Y4M" }, + { .string = "T7H4M" }, + { .string = "1Y6M" }, + { .string = "PT4294967296S" }, + { .string = "PT99999999999S" }, + { .string = "P99999999999Y99999999999M99999999999D" + "T99999999999H99999999999M99999999999S" }, + }; + isc_buffer_t buf1; + cfg_parser_t *p1 = NULL; + cfg_obj_t *c1 = NULL; + bool must_fail = false; + + for (size_t i = 0; i < ARRAY_SIZE(durations); i++) { + const cfg_listelt_t *element; + const cfg_obj_t *kasps = NULL; + const char cfg_tpl[] = + "dnssec-policy \"dp\"\n" + "{\nkeys {csk lifetime %s algorithm rsasha256;};\n};\n"; + char conf[sizeof(cfg_tpl) + CFG_DURATION_MAXLEN] = { 0 }; + char out[CFG_DURATION_MAXLEN] = { 0 }; + cfg_printer_t pctx = { .f = output, .closure = out }; + + if (durations[i].string == NULL) { + must_fail = true; + continue; + } + + snprintf(&conf[0], sizeof(conf), cfg_tpl, durations[i].string); + + isc_buffer_init(&buf1, conf, strlen(conf) - 1); + isc_buffer_add(&buf1, strlen(conf) - 1); + + /* Parse with default line numbering */ + result = cfg_parser_create(mctx, lctx, &p1); + assert_int_equal(result, ISC_R_SUCCESS); + + result = cfg_parse_buffer(p1, &buf1, "text1", 0, + &cfg_type_namedconf, 0, &c1); + if (must_fail) { + assert_int_equal(result, DNS_R_BADTTL); + cfg_parser_destroy(&p1); + continue; + } + assert_int_equal(result, ISC_R_SUCCESS); + + (void)cfg_map_get(c1, "dnssec-policy", &kasps); + assert_non_null(kasps); + for (element = cfg_list_first(kasps); element != NULL; + element = cfg_list_next(element)) + { + const cfg_listelt_t *key_element; + const cfg_obj_t *lifetime = NULL; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *kopts = NULL; + cfg_obj_t *kconf = cfg_listelt_value(element); + int cmp; + + assert_non_null(kconf); + + kopts = cfg_tuple_get(kconf, "options"); + result = cfg_map_get(kopts, "keys", &keys); + + key_element = cfg_list_first(keys); + assert_non_null(key_element); + + key = cfg_listelt_value(key_element); + assert_non_null(key); + + lifetime = cfg_tuple_get(key, "lifetime"); + assert_non_null(lifetime); + + assert_int_equal(durations[i].time, + cfg_obj_asduration(lifetime)); + + cfg_print_duration_or_unlimited(&pctx, lifetime); + cmp = strncasecmp(durations[i].out != NULL + ? durations[i].out + : durations[i].string, + out, strlen(durations[i].string)); + assert_int_equal(cmp, 0); + } + + cfg_obj_destroy(p1, &c1); + cfg_parser_destroy(&p1); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(duration) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(setup_test_group, teardown_test_group) diff --git a/tests/isccfg/parser_test.c b/tests/isccfg/parser_test.c new file mode 100644 index 0000000..89a3ba4 --- /dev/null +++ b/tests/isccfg/parser_test.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/lex.h> +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/types.h> +#include <isc/util.h> + +#include <isccfg/cfg.h> +#include <isccfg/grammar.h> +#include <isccfg/namedconf.h> + +#include <tests/isc.h> + +isc_log_t *lctx = NULL; +static isc_logcategory_t categories[] = { { "", 0 }, + { "client", 0 }, + { "network", 0 }, + { "update", 0 }, + { "queries", 0 }, + { "unmatched", 0 }, + { "update-security", 0 }, + { "query-errors", 0 }, + { NULL, 0 } }; + +ISC_SETUP_TEST_IMPL(group) { + isc_result_t result; + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + + isc_log_create(mctx, &lctx, &logconfig); + isc_log_registercategories(lctx, categories); + isc_log_setcontext(lctx); + + destination.file.stream = stderr; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, &destination, 0); + result = isc_log_usechannel(logconfig, "stderr", NULL, NULL); + + if (result != ISC_R_SUCCESS) { + return (-1); + } + + return (0); +} + +ISC_TEARDOWN_TEST_IMPL(group) { + if (lctx == NULL) { + return (-1); + } + + isc_log_setcontext(NULL); + isc_log_destroy(&lctx); + + return (0); +} + +/* mimic calling nzf_append() */ +static void +append(void *arg, const char *str, int len) { + char *buf = arg; + size_t l = strlen(buf); + snprintf(buf + l, 1024 - l, "%.*s", len, str); +} + +ISC_RUN_TEST_IMPL(addzoneconf) { + isc_result_t result; + isc_buffer_t b; + cfg_parser_t *p = NULL; + const char *tests[] = { + "zone \"test4.baz\" { type primary; file \"e.db\"; };", + "zone \"test/.baz\" { type primary; file \"e.db\"; };", + "zone \"test\\\".baz\" { type primary; file \"e.db\"; };", + "zone \"test\\.baz\" { type primary; file \"e.db\"; };", + "zone \"test\\\\.baz\" { type primary; file \"e.db\"; };", + "zone \"test\\032.baz\" { type primary; file \"e.db\"; };", + "zone \"test\\010.baz\" { type primary; file \"e.db\"; };" + }; + char buf[1024]; + + /* Parse with default line numbering */ + result = cfg_parser_create(mctx, lctx, &p); + assert_int_equal(result, ISC_R_SUCCESS); + + for (size_t i = 0; i < ARRAY_SIZE(tests); i++) { + cfg_obj_t *conf = NULL; + const cfg_obj_t *obj = NULL, *zlist = NULL; + + isc_buffer_constinit(&b, tests[i], strlen(tests[i])); + isc_buffer_add(&b, strlen(tests[i])); + + result = cfg_parse_buffer(p, &b, "text1", 0, + &cfg_type_namedconf, 0, &conf); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Mimic calling nzf_append() from bin/named/server.c + * and check that the output matches the input. + */ + result = cfg_map_get(conf, "zone", &zlist); + assert_int_equal(result, ISC_R_SUCCESS); + + obj = cfg_listelt_value(cfg_list_first(zlist)); + assert_ptr_not_equal(obj, NULL); + + strlcpy(buf, "zone ", sizeof(buf)); + cfg_printx(obj, CFG_PRINTER_ONELINE, append, buf); + strlcat(buf, ";", sizeof(buf)); + assert_string_equal(tests[i], buf); + + cfg_obj_destroy(p, &conf); + cfg_parser_reset(p); + } + + cfg_parser_destroy(&p); +} + +/* test cfg_parse_buffer() */ +ISC_RUN_TEST_IMPL(parse_buffer) { + isc_result_t result; + unsigned char text[] = "options\n{\nrecursion yes;\n};\n"; + isc_buffer_t buf1, buf2; + cfg_parser_t *p1 = NULL, *p2 = NULL; + cfg_obj_t *c1 = NULL, *c2 = NULL; + + isc_buffer_init(&buf1, &text[0], sizeof(text) - 1); + isc_buffer_add(&buf1, sizeof(text) - 1); + + /* Parse with default line numbering */ + result = cfg_parser_create(mctx, lctx, &p1); + assert_int_equal(result, ISC_R_SUCCESS); + + result = cfg_parse_buffer(p1, &buf1, "text1", 0, &cfg_type_namedconf, 0, + &c1); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(p1->line, 5); + + isc_buffer_init(&buf2, &text[0], sizeof(text) - 1); + isc_buffer_add(&buf2, sizeof(text) - 1); + + /* Parse with changed line number */ + result = cfg_parser_create(mctx, lctx, &p2); + assert_int_equal(result, ISC_R_SUCCESS); + + result = cfg_parse_buffer(p2, &buf2, "text2", 100, &cfg_type_namedconf, + 0, &c2); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(p2->line, 104); + + cfg_obj_destroy(p1, &c1); + cfg_obj_destroy(p2, &c2); + + cfg_parser_destroy(&p1); + cfg_parser_destroy(&p2); +} + +/* test cfg_map_firstclause() */ +ISC_RUN_TEST_IMPL(cfg_map_firstclause) { + const char *name = NULL; + const void *clauses = NULL; + unsigned int idx; + + name = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &idx); + assert_non_null(name); + assert_non_null(clauses); + assert_int_equal(idx, 0); +} + +/* test cfg_map_nextclause() */ +ISC_RUN_TEST_IMPL(cfg_map_nextclause) { + const char *name = NULL; + const void *clauses = NULL; + unsigned int idx; + + name = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &idx); + assert_non_null(name); + assert_non_null(clauses); + assert_int_equal(idx, ISC_R_SUCCESS); + + do { + name = cfg_map_nextclause(&cfg_type_zoneopts, &clauses, &idx); + if (name != NULL) { + assert_non_null(clauses); + } else { + assert_null(clauses); + assert_int_equal(idx, 0); + } + } while (name != NULL); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY(addzoneconf) +ISC_TEST_ENTRY(parse_buffer) +ISC_TEST_ENTRY(cfg_map_firstclause) +ISC_TEST_ENTRY(cfg_map_nextclause) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN_CUSTOM(setup_test_group, teardown_test_group) diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am new file mode 100644 index 0000000..6bd4b80 --- /dev/null +++ b/tests/libtest/Makefile.am @@ -0,0 +1,25 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) + +check_LTLIBRARIES = libtest.la + +libtest_la_SOURCES = \ + ../include/tests/dns.h \ + ../include/tests/isc.h \ + ../include/tests/ns.h \ + dns.c \ + isc.c \ + ns.c + +include $(top_srcdir)/Makefile.tests diff --git a/tests/libtest/Makefile.in b/tests/libtest/Makefile.in new file mode 100644 index 0000000..8e89774 --- /dev/null +++ b/tests/libtest/Makefile.in @@ -0,0 +1,1157 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +TESTS = +subdir = tests/libtest +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +libtest_la_LIBADD = +am_libtest_la_OBJECTS = dns.lo isc.lo ns.lo +libtest_la_OBJECTS = $(am_libtest_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/dns.Plo ./$(DEPDIR)/isc.Plo \ + ./$(DEPDIR)/ns.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtest_la_SOURCES) +DIST_SOURCES = $(libtest_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBUV_CFLAGS) -I$(top_srcdir)/lib/isc \ + $(CMOCKA_CFLAGS) -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +check_LTLIBRARIES = libtest.la +libtest_la_SOURCES = \ + ../include/tests/dns.h \ + ../include/tests/isc.h \ + ../include/tests/ns.h \ + dns.c \ + isc.c \ + ns.c + +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/libtest/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/libtest/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkLTLIBRARIES: + -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) + @list='$(check_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES) $(EXTRA_libtest_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ns.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_LTLIBRARIES) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_LTLIBRARIES) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/dns.Plo + -rm -f ./$(DEPDIR)/isc.Plo + -rm -f ./$(DEPDIR)/ns.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/dns.Plo + -rm -f ./$(DEPDIR)/isc.Plo + -rm -f ./$(DEPDIR)/ns.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkLTLIBRARIES clean-generic \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am test-am test-local uninstall uninstall-am \ + unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/libtest/dns.c b/tests/libtest/dns.c new file mode 100644 index 0000000..ae3748f --- /dev/null +++ b/tests/libtest/dns.c @@ -0,0 +1,501 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/buffer.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/hex.h> +#include <isc/lex.h> +#include <isc/managers.h> +#include <isc/mem.h> +#include <isc/netmgr.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/stdio.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/callbacks.h> +#include <dns/db.h> +#include <dns/fixedname.h> +#include <dns/log.h> +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include <tests/dns.h> + +dns_zonemgr_t *zonemgr = NULL; + +/* + * Create a view. + */ +isc_result_t +dns_test_makeview(const char *name, bool with_cache, dns_view_t **viewp) { + isc_result_t result; + dns_view_t *view = NULL; + dns_cache_t *cache = NULL; + + result = dns_view_create(mctx, dns_rdataclass_in, name, &view); + if (result != ISC_R_SUCCESS) { + return (result); + } + + if (with_cache) { + result = dns_cache_create(mctx, mctx, taskmgr, timermgr, + dns_rdataclass_in, "", "rbt", 0, NULL, + &cache); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + dns_view_setcache(view, cache, false); + /* + * Reference count for "cache" is now at 2, so decrement it in + * order for the cache to be automatically freed when "view" + * gets freed. + */ + dns_cache_detach(&cache); + } + + *viewp = view; + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, + bool createview) { + dns_fixedname_t fixed_origin; + dns_zone_t *zone = NULL; + isc_result_t result; + dns_name_t *origin; + + REQUIRE(view == NULL || !createview); + + /* + * Create the zone structure. + */ + result = dns_zone_create(&zone, mctx); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Set zone type and origin. + */ + dns_zone_settype(zone, dns_zone_primary); + origin = dns_fixedname_initname(&fixed_origin); + result = dns_name_fromstring(origin, name, 0, NULL); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + result = dns_zone_setorigin(zone, origin); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + + /* + * If requested, create a view. + */ + if (createview) { + result = dns_test_makeview("view", false, &view); + if (result != ISC_R_SUCCESS) { + goto detach_zone; + } + } + + /* + * If a view was passed as an argument or created above, attach the + * created zone to it. Otherwise, set the zone's class to IN. + */ + if (view != NULL) { + dns_zone_setview(zone, view); + dns_zone_setclass(zone, view->rdclass); + dns_view_addzone(view, zone); + } else { + dns_zone_setclass(zone, dns_rdataclass_in); + } + + *zonep = zone; + + return (ISC_R_SUCCESS); + +detach_zone: + dns_zone_detach(&zone); + + return (result); +} + +isc_result_t +dns_test_setupzonemgr(void) { + isc_result_t result; + REQUIRE(zonemgr == NULL); + + result = dns_zonemgr_create(mctx, taskmgr, timermgr, netmgr, &zonemgr); + return (result); +} + +isc_result_t +dns_test_managezone(dns_zone_t *zone) { + isc_result_t result; + REQUIRE(zonemgr != NULL); + + result = dns_zonemgr_setsize(zonemgr, 1); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_zonemgr_managezone(zonemgr, zone); + return (result); +} + +void +dns_test_releasezone(dns_zone_t *zone) { + REQUIRE(zonemgr != NULL); + dns_zonemgr_releasezone(zonemgr, zone); +} + +void +dns_test_closezonemgr(void) { + REQUIRE(zonemgr != NULL); + + dns_zonemgr_shutdown(zonemgr); + dns_zonemgr_detach(&zonemgr); +} + +/* + * Sleep for 'usec' microseconds. + */ +void +dns_test_nap(uint32_t usec) { + struct timespec ts; + + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + nanosleep(&ts, NULL); +} + +isc_result_t +dns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile) { + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name; + + name = dns_fixedname_initname(&fixed); + + result = dns_name_fromstring(name, origin, 0, NULL); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in, 0, + NULL, db); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_db_load(*db, testfile, dns_masterformat_text, 0); + return (result); +} + +static int +fromhex(char c) { + if (c >= '0' && c <= '9') { + return (c - '0'); + } else if (c >= 'a' && c <= 'f') { + return (c - 'a' + 10); + } else if (c >= 'A' && c <= 'F') { + return (c - 'A' + 10); + } + + printf("bad input format: %02x\n", c); + exit(3); +} + +/* + * 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); + assert_int_equal(result, ISC_R_SUCCESS); + + return (buf); +} + +isc_result_t +dns_test_getdata(const char *file, unsigned char *buf, size_t bufsiz, + size_t *sizep) { + isc_result_t result; + unsigned char *bp; + char *rp, *wp; + char s[BUFSIZ]; + size_t len, i; + FILE *f = NULL; + int n; + + result = isc_stdio_open(file, "r", &f); + if (result != ISC_R_SUCCESS) { + return (result); + } + + bp = buf; + while (fgets(s, sizeof(s), f) != NULL) { + rp = s; + wp = s; + len = 0; + while (*rp != '\0') { + if (*rp == '#') { + break; + } + if (*rp != ' ' && *rp != '\t' && *rp != '\r' && + *rp != '\n') + { + *wp++ = *rp; + len++; + } + rp++; + } + if (len == 0U) { + continue; + } + if (len % 2 != 0U) { + result = ISC_R_UNEXPECTEDEND; + break; + } + if (len > bufsiz * 2) { + result = ISC_R_NOSPACE; + break; + } + rp = s; + for (i = 0; i < len; i += 2) { + n = fromhex(*rp++); + n *= 16; + n += fromhex(*rp++); + *bp++ = n; + } + } + + if (result == ISC_R_SUCCESS) { + *sizep = bp - buf; + } + + isc_stdio_close(f); + return (result); +} + +static void +nullmsg(dns_rdatacallbacks_t *cb, const char *fmt, ...) { + UNUSED(cb); + UNUSED(fmt); +} + +isc_result_t +dns_test_rdatafromstring(dns_rdata_t *rdata, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype, unsigned char *dst, + size_t dstlen, const char *src, bool warnings) { + dns_rdatacallbacks_t callbacks; + isc_buffer_t source, target; + isc_lex_t *lex = NULL; + isc_lexspecials_t specials = { 0 }; + isc_result_t result; + size_t length; + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + REQUIRE(dst != NULL); + REQUIRE(src != NULL); + + /* + * Set up source to hold the input string. + */ + length = strlen(src); + isc_buffer_constinit(&source, src, length); + isc_buffer_add(&source, length); + + /* + * Create a lexer as one is required by dns_rdata_fromtext(). + */ + result = isc_lex_create(mctx, 64, &lex); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Set characters which will be treated as valid multi-line RDATA + * delimiters while reading the source string. These should match + * specials from lib/dns/master.c. + */ + specials[0] = 1; + specials['('] = 1; + specials[')'] = 1; + specials['"'] = 1; + isc_lex_setspecials(lex, specials); + + /* + * Expect DNS masterfile comments. + */ + isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); + + /* + * Point lexer at source. + */ + result = isc_lex_openbuffer(lex, &source); + if (result != ISC_R_SUCCESS) { + goto destroy_lexer; + } + + /* + * Set up target for storing uncompressed wire form of provided RDATA. + */ + isc_buffer_init(&target, dst, dstlen); + + /* + * Set up callbacks so warnings and errors are not printed. + */ + if (!warnings) { + dns_rdatacallbacks_init(&callbacks); + callbacks.warn = callbacks.error = nullmsg; + } + + /* + * Parse input string, determining result. + */ + result = dns_rdata_fromtext(rdata, rdclass, rdtype, lex, dns_rootname, + 0, mctx, &target, &callbacks); + +destroy_lexer: + isc_lex_destroy(&lex); + + return (result); +} + +void +dns_test_namefromstring(const char *namestr, dns_fixedname_t *fname) { + size_t length; + isc_buffer_t *b = NULL; + isc_result_t result; + dns_name_t *name; + + length = strlen(namestr); + + name = dns_fixedname_initname(fname); + + isc_buffer_allocate(mctx, &b, length); + + isc_buffer_putmem(b, (const unsigned char *)namestr, length); + result = dns_name_fromtext(name, b, dns_rootname, 0, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_free(&b); +} + +isc_result_t +dns_test_difffromchanges(dns_diff_t *diff, const zonechange_t *changes, + bool warnings) { + isc_result_t result = ISC_R_SUCCESS; + unsigned char rdata_buf[1024]; + dns_difftuple_t *tuple = NULL; + isc_consttextregion_t region; + dns_rdatatype_t rdatatype; + dns_fixedname_t fixedname; + dns_rdata_t rdata; + dns_name_t *name; + size_t i; + + REQUIRE(diff != NULL); + REQUIRE(changes != NULL); + + dns_diff_init(mctx, diff); + + for (i = 0; changes[i].owner != NULL; i++) { + /* + * Parse owner name. + */ + name = dns_fixedname_initname(&fixedname); + result = dns_name_fromstring(name, changes[i].owner, 0, mctx); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Parse RDATA type. + */ + region.base = changes[i].type; + region.length = strlen(changes[i].type); + result = dns_rdatatype_fromtext(&rdatatype, + (isc_textregion_t *)®ion); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Parse RDATA. + */ + dns_rdata_init(&rdata); + result = dns_test_rdatafromstring( + &rdata, dns_rdataclass_in, rdatatype, rdata_buf, + sizeof(rdata_buf), changes[i].rdata, warnings); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Create a diff tuple for the parsed change and append it to + * the diff. + */ + result = dns_difftuple_create(mctx, changes[i].op, name, + changes[i].ttl, &rdata, &tuple); + if (result != ISC_R_SUCCESS) { + break; + } + dns_diff_append(diff, &tuple); + } + + if (result != ISC_R_SUCCESS) { + dns_diff_clear(diff); + } + + return (result); +} diff --git a/tests/libtest/isc.c b/tests/libtest/isc.c new file mode 100644 index 0000000..970a4b1 --- /dev/null +++ b/tests/libtest/isc.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <time.h> + +#include <isc/buffer.h> +#include <isc/hash.h> +#include <isc/managers.h> +#include <isc/mem.h> +#include <isc/os.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include "netmgr_p.h" +#include "task_p.h" +#include "timer_p.h" + +#include <tests/isc.h> + +isc_mem_t *mctx = NULL; +isc_taskmgr_t *taskmgr = NULL; +isc_timermgr_t *timermgr = NULL; +isc_nm_t *netmgr = NULL; +unsigned int workers = 0; +isc_task_t *maintask = NULL; + +int +setup_managers(void **state) { + isc_result_t result; + + UNUSED(state); + + REQUIRE(mctx != NULL); + + if (workers == 0) { + char *env_workers = getenv("ISC_TASK_WORKERS"); + if (env_workers != NULL) { + workers = atoi(env_workers); + } else { + workers = isc_os_ncpus(); + } + INSIST(workers > 0); + } + + result = isc_managers_create(mctx, workers, 0, &netmgr, &taskmgr, + &timermgr); + if (result != ISC_R_SUCCESS) { + return (-1); + } + + result = isc_task_create_bound(taskmgr, 0, &maintask, 0); + if (result != ISC_R_SUCCESS) { + return (-1); + } + + isc_taskmgr_setexcltask(taskmgr, maintask); + + return (0); +} + +int +teardown_managers(void **state) { + UNUSED(state); + + isc_task_detach(&maintask); + isc_managers_destroy(&netmgr, &taskmgr, &timermgr); + + return (0); +} diff --git a/tests/libtest/ns.c b/tests/libtest/ns.c new file mode 100644 index 0000000..4a53ad8 --- /dev/null +++ b/tests/libtest/ns.c @@ -0,0 +1,669 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> +#include <stdbool.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#include <isc/buffer.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/managers.h> +#include <isc/mem.h> +#include <isc/netmgr.h> +#include <isc/os.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/resource.h> +#include <isc/result.h> +#include <isc/stdio.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/cache.h> +#include <dns/db.h> +#include <dns/dispatch.h> +#include <dns/fixedname.h> +#include <dns/log.h> +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include <ns/client.h> +#include <ns/hooks.h> +#include <ns/interfacemgr.h> +#include <ns/server.h> + +#include <tests/ns.h> + +dns_dispatchmgr_t *dispatchmgr = NULL; +ns_clientmgr_t *clientmgr = NULL; +ns_interfacemgr_t *interfacemgr = NULL; +ns_server_t *sctx = NULL; +bool debug_mem_record = true; + +static isc_result_t +matchview(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, + dns_message_t *message, dns_aclenv_t *env, isc_result_t *sigresultp, + dns_view_t **viewp) { + UNUSED(srcaddr); + UNUSED(destaddr); + UNUSED(message); + UNUSED(env); + UNUSED(sigresultp); + UNUSED(viewp); + + return (ISC_R_NOTIMPLEMENTED); +} + +int +setup_server(void **state) { + isc_result_t result; + ns_listenlist_t *listenon = NULL; + in_port_t port = 5300 + isc_random8(); + + setup_managers(state); + + ns_server_create(mctx, matchview, &sctx); + + result = dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr); + if (result != ISC_R_SUCCESS) { + return (-1); + } + + result = ns_interfacemgr_create(mctx, sctx, taskmgr, timermgr, netmgr, + dispatchmgr, maintask, NULL, workers, + false, &interfacemgr); + if (result != ISC_R_SUCCESS) { + return (-1); + } + + result = ns_listenlist_default(mctx, port, true, AF_INET, &listenon); + if (result != ISC_R_SUCCESS) { + return (-1); + } + + ns_interfacemgr_setlistenon4(interfacemgr, listenon); + ns_listenlist_detach(&listenon); + + clientmgr = ns_interfacemgr_getclientmgr(interfacemgr); + + return (0); +} + +int +teardown_server(void **state) { + if (interfacemgr != NULL) { + ns_interfacemgr_shutdown(interfacemgr); + ns_interfacemgr_detach(&interfacemgr); + } + + if (dispatchmgr != NULL) { + dns_dispatchmgr_detach(&dispatchmgr); + } + + if (sctx != NULL) { + ns_server_detach(&sctx); + } + + teardown_managers(state); + return (0); +} + +static dns_zone_t *served_zone = NULL; + +/* + * We don't want to use netmgr-based client accounting, we need to emulate it. + */ +atomic_uint_fast32_t client_refs[32]; +atomic_uintptr_t client_addrs[32]; + +void +isc__nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp FLARG) { + ns_client_t *client = (ns_client_t *)source; + int i; + + for (i = 0; i < 32; i++) { + if (atomic_load(&client_addrs[i]) == (uintptr_t)client) { + break; + } + } + INSIST(i < 32); + INSIST(atomic_load(&client_refs[i]) > 0); + + atomic_fetch_add(&client_refs[i], 1); + + *targetp = source; + return; +} + +void +isc__nmhandle_detach(isc_nmhandle_t **handlep FLARG) { + isc_nmhandle_t *handle = *handlep; + ns_client_t *client = (ns_client_t *)handle; + int i; + + *handlep = NULL; + + for (i = 0; i < 32; i++) { + if (atomic_load(&client_addrs[i]) == (uintptr_t)client) { + break; + } + } + INSIST(i < 32); + + if (atomic_fetch_sub(&client_refs[i], 1) == 1) { + dns_view_detach(&client->view); + client->state = 4; + ns__client_reset_cb(client); + ns__client_put_cb(client); + isc_mem_put(mctx, client, sizeof(ns_client_t)); + atomic_store(&client_addrs[i], (uintptr_t)NULL); + } + + return; +} + +isc_result_t +ns_test_serve_zone(const char *zonename, const char *filename, + dns_view_t *view) { + isc_result_t result; + dns_db_t *db = NULL; + + /* + * Prepare zone structure for further processing. + */ + result = dns_test_makezone(zonename, &served_zone, view, false); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Start zone manager. + */ + result = dns_test_setupzonemgr(); + if (result != ISC_R_SUCCESS) { + goto free_zone; + } + + /* + * Add the zone to the zone manager. + */ + result = dns_test_managezone(served_zone); + if (result != ISC_R_SUCCESS) { + goto close_zonemgr; + } + + view->nocookieudp = 512; + + /* + * Set path to the master file for the zone and then load it. + */ + dns_zone_setfile(served_zone, filename, dns_masterformat_text, + &dns_master_style_default); + result = dns_zone_load(served_zone, false); + if (result != ISC_R_SUCCESS) { + goto release_zone; + } + + /* + * The zone should now be loaded; test it. + */ + result = dns_zone_getdb(served_zone, &db); + if (result != ISC_R_SUCCESS) { + goto release_zone; + } + if (db != NULL) { + dns_db_detach(&db); + } + + return (ISC_R_SUCCESS); + +release_zone: + dns_test_releasezone(served_zone); +close_zonemgr: + dns_test_closezonemgr(); +free_zone: + dns_zone_detach(&served_zone); + + return (result); +} + +void +ns_test_cleanup_zone(void) { + dns_test_releasezone(served_zone); + dns_test_closezonemgr(); + + dns_zone_detach(&served_zone); +} + +isc_result_t +ns_test_getclient(ns_interface_t *ifp0, bool tcp, ns_client_t **clientp) { + isc_result_t result; + ns_client_t *client = isc_mem_get(mctx, sizeof(ns_client_t)); + int i; + + UNUSED(ifp0); + UNUSED(tcp); + + result = ns__client_setup(client, clientmgr, true); + + for (i = 0; i < 32; i++) { + if (atomic_load(&client_addrs[i]) == (uintptr_t)NULL || + atomic_load(&client_addrs[i]) == (uintptr_t)client) + { + break; + } + } + REQUIRE(i < 32); + + atomic_store(&client_refs[i], 2); + atomic_store(&client_addrs[i], (uintptr_t)client); + client->handle = (isc_nmhandle_t *)client; /* Hack */ + *clientp = client; + + return (result); +} + +/*% + * Synthesize a DNS message based on supplied QNAME, QTYPE and flags, then + * parse it and store the results in client->message. + */ +static isc_result_t +attach_query_msg_to_client(ns_client_t *client, const char *qnamestr, + dns_rdatatype_t qtype, unsigned int qflags) { + dns_rdataset_t *qrdataset = NULL; + dns_message_t *message = NULL; + unsigned char query[65536]; + dns_name_t *qname = NULL; + isc_buffer_t querybuf; + dns_compress_t cctx; + isc_result_t result; + + REQUIRE(client != NULL); + REQUIRE(qnamestr != NULL); + + /* + * Create a new DNS message holding a query. + */ + dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); + + /* + * Set query ID to a random value. + */ + message->id = isc_random16(); + + /* + * Set query flags as requested by the caller. + */ + message->flags = qflags; + + /* + * Allocate structures required to construct the query. + */ + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) { + goto destroy_message; + } + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) { + goto put_rdataset; + } + + /* + * Convert "qnamestr" to a DNS name, create a question rdataset of + * class IN and type "qtype", link the two and add the result to the + * QUESTION section of the query. + */ + result = dns_name_fromstring(qname, qnamestr, 0, mctx); + if (result != ISC_R_SUCCESS) { + goto put_name; + } + dns_rdataset_makequestion(qrdataset, dns_rdataclass_in, qtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + /* + * Render the query. + */ + dns_compress_init(&cctx, -1, mctx); + isc_buffer_init(&querybuf, query, sizeof(query)); + result = dns_message_renderbegin(message, &cctx, &querybuf); + if (result != ISC_R_SUCCESS) { + goto destroy_message; + } + result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); + if (result != ISC_R_SUCCESS) { + goto destroy_message; + } + result = dns_message_renderend(message); + if (result != ISC_R_SUCCESS) { + goto destroy_message; + } + dns_compress_invalidate(&cctx); + + /* + * Destroy the created message as it was rendered into "querybuf" and + * the latter is all we are going to need from now on. + */ + dns_message_detach(&message); + + /* + * Parse the rendered query, storing results in client->message. + */ + isc_buffer_first(&querybuf); + return (dns_message_parse(client->message, &querybuf, 0)); + +put_name: + dns_message_puttempname(message, &qname); +put_rdataset: + dns_message_puttemprdataset(message, &qrdataset); +destroy_message: + dns_message_detach(&message); + + return (result); +} + +/*% + * A hook action which stores the query context pointed to by "arg" at + * "data". Causes execution to be interrupted at hook insertion + * point. + */ +static ns_hookresult_t +extract_qctx(void *arg, void *data, isc_result_t *resultp) { + query_ctx_t **qctxp; + query_ctx_t *qctx; + + REQUIRE(arg != NULL); + REQUIRE(data != NULL); + REQUIRE(resultp != NULL); + + /* + * qctx is a stack variable in lib/ns/query.c. Its contents need to be + * duplicated or otherwise they will become invalidated once the stack + * gets unwound. + */ + qctx = isc_mem_get(mctx, sizeof(*qctx)); + if (qctx != NULL) { + memmove(qctx, (query_ctx_t *)arg, sizeof(*qctx)); + } + + qctxp = (query_ctx_t **)data; + /* + * If memory allocation failed, the supplied pointer will simply be set + * to NULL. We rely on the user of this hook to react properly. + */ + *qctxp = qctx; + *resultp = ISC_R_UNSET; + + return (NS_HOOK_RETURN); +} + +/*% + * Initialize a query context for "client" and store it in "qctxp". + * + * Requires: + * + * \li "client->message" to hold a parsed DNS query. + */ +static isc_result_t +create_qctx_for_client(ns_client_t *client, query_ctx_t **qctxp) { + ns_hooktable_t *saved_hook_table = NULL, *query_hooks = NULL; + const ns_hook_t hook = { + .action = extract_qctx, + .action_data = qctxp, + }; + + REQUIRE(client != NULL); + REQUIRE(qctxp != NULL); + REQUIRE(*qctxp == NULL); + + /* + * Call ns_query_start() to initialize a query context for given + * client, but first hook into query_setup() so that we can just + * extract an initialized query context, without kicking off any + * further processing. Make sure we do not overwrite any previously + * set hooks. + */ + + ns_hooktable_create(mctx, &query_hooks); + ns_hook_add(query_hooks, mctx, NS_QUERY_SETUP, &hook); + + saved_hook_table = ns__hook_table; + ns__hook_table = query_hooks; + + ns_query_start(client, client->handle); + + ns__hook_table = saved_hook_table; + ns_hooktable_free(mctx, (void **)&query_hooks); + + isc_nmhandle_detach(&client->reqhandle); + + if (*qctxp == NULL) { + return (ISC_R_NOMEMORY); + } else { + return (ISC_R_SUCCESS); + } +} + +isc_result_t +ns_test_qctx_create(const ns_test_qctx_create_params_t *params, + query_ctx_t **qctxp) { + ns_client_t *client = NULL; + isc_result_t result; + isc_nmhandle_t *handle = NULL; + + REQUIRE(params != NULL); + REQUIRE(params->qname != NULL); + REQUIRE(qctxp != NULL); + REQUIRE(*qctxp == NULL); + + /* + * Allocate and initialize a client structure. + */ + result = ns_test_getclient(NULL, false, &client); + if (result != ISC_R_SUCCESS) { + return (result); + } + TIME_NOW(&client->tnow); + + /* + * Every client needs to belong to a view. + */ + result = dns_test_makeview("view", params->with_cache, &client->view); + if (result != ISC_R_SUCCESS) { + goto detach_client; + } + + /* + * Synthesize a DNS query using given QNAME, QTYPE and flags, storing + * it in client->message. + */ + result = attach_query_msg_to_client(client, params->qname, + params->qtype, params->qflags); + if (result != ISC_R_SUCCESS) { + goto detach_view; + } + + /* + * Allow recursion for the client. As NS_CLIENTATTR_RA normally gets + * set in ns__client_request(), i.e. earlier than the unit tests hook + * into the call chain, just set it manually. + */ + client->attributes |= NS_CLIENTATTR_RA; + + /* + * Create a query context for a client sending the previously + * synthesized query. + */ + result = create_qctx_for_client(client, qctxp); + if (result != ISC_R_SUCCESS) { + goto detach_query; + } + + /* + * The reference count for "client" is now at 2, so we need to + * decrement it in order for it to drop to zero when "qctx" gets + * destroyed. + */ + handle = client->handle; + isc_nmhandle_detach(&handle); + + return (ISC_R_SUCCESS); + +detach_query: + dns_message_detach(&client->message); +detach_view: + dns_view_detach(&client->view); +detach_client: + isc_nmhandle_detach(&client->handle); + + return (result); +} + +void +ns_test_qctx_destroy(query_ctx_t **qctxp) { + query_ctx_t *qctx; + + REQUIRE(qctxp != NULL); + REQUIRE(*qctxp != NULL); + + qctx = *qctxp; + *qctxp = NULL; + + if (qctx->zone != NULL) { + dns_zone_detach(&qctx->zone); + } + if (qctx->db != NULL) { + dns_db_detach(&qctx->db); + } + if (qctx->client != NULL) { + isc_nmhandle_detach(&qctx->client->handle); + } + + isc_mem_put(mctx, qctx, sizeof(*qctx)); +} + +ns_hookresult_t +ns_test_hook_catch_call(void *arg, void *data, isc_result_t *resultp) { + UNUSED(arg); + UNUSED(data); + + *resultp = ISC_R_UNSET; + + return (NS_HOOK_RETURN); +} + +isc_result_t +ns_test_loaddb(dns_db_t **db, dns_dbtype_t dbtype, const char *origin, + const char *testfile) { + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name; + + name = dns_fixedname_initname(&fixed); + + result = dns_name_fromstring(name, origin, 0, NULL); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_db_create(mctx, "rbt", name, dbtype, dns_rdataclass_in, 0, + NULL, db); + if (result != ISC_R_SUCCESS) { + return (result); + } + + result = dns_db_load(*db, testfile, dns_masterformat_text, 0); + return (result); +} + +static int +fromhex(char c) { + if (c >= '0' && c <= '9') { + return (c - '0'); + } else if (c >= 'a' && c <= 'f') { + return (c - 'a' + 10); + } else if (c >= 'A' && c <= 'F') { + return (c - 'A' + 10); + } + + printf("bad input format: %02x\n", c); + exit(3); +} + +isc_result_t +ns_test_getdata(const char *file, unsigned char *buf, size_t bufsiz, + size_t *sizep) { + isc_result_t result; + unsigned char *bp; + char *rp, *wp; + char s[BUFSIZ]; + size_t len, i; + FILE *f = NULL; + int n; + + result = isc_stdio_open(file, "r", &f); + if (result != ISC_R_SUCCESS) { + return (result); + } + + bp = buf; + while (fgets(s, sizeof(s), f) != NULL) { + rp = s; + wp = s; + len = 0; + while (*rp != '\0') { + if (*rp == '#') { + break; + } + if (*rp != ' ' && *rp != '\t' && *rp != '\r' && + *rp != '\n') + { + *wp++ = *rp; + len++; + } + rp++; + } + if (len == 0U) { + continue; + } + if (len % 2 != 0U) { + CHECK(ISC_R_UNEXPECTEDEND); + } + if (len > bufsiz * 2) { + CHECK(ISC_R_NOSPACE); + } + rp = s; + for (i = 0; i < len; i += 2) { + n = fromhex(*rp++); + n *= 16; + n += fromhex(*rp++); + *bp++ = n; + } + } + + *sizep = bp - buf; + + result = ISC_R_SUCCESS; + +cleanup: + isc_stdio_close(f); + return (result); +} diff --git a/tests/ns/Makefile.am b/tests/ns/Makefile.am new file mode 100644 index 0000000..33f91d8 --- /dev/null +++ b/tests/ns/Makefile.am @@ -0,0 +1,25 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBUV_CFLAGS) \ + -I$(top_srcdir)/lib/isc \ + -I$(top_srcdir)/lib/dns + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) \ + $(LIBUV_LIBS) + +check_PROGRAMS = \ + listenlist_test \ + notify_test \ + plugin_test \ + query_test + +EXTRA_DIST = testdata + +include $(top_srcdir)/Makefile.tests diff --git a/tests/ns/Makefile.in b/tests/ns/Makefile.in new file mode 100644 index 0000000..efa0cc9 --- /dev/null +++ b/tests/ns/Makefile.in @@ -0,0 +1,1219 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +check_PROGRAMS = listenlist_test$(EXEEXT) notify_test$(EXEEXT) \ + plugin_test$(EXEEXT) query_test$(EXEEXT) +subdir = tests/ns +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_perl_module.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_python_module.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +listenlist_test_SOURCES = listenlist_test.c +listenlist_test_OBJECTS = listenlist_test.$(OBJEXT) +listenlist_test_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +listenlist_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) $(am__DEPENDENCIES_1) \ + $(top_builddir)/tests/libtest/libtest.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +notify_test_SOURCES = notify_test.c +notify_test_OBJECTS = notify_test.$(OBJEXT) +notify_test_LDADD = $(LDADD) +notify_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(am__DEPENDENCIES_1) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +plugin_test_SOURCES = plugin_test.c +plugin_test_OBJECTS = plugin_test.$(OBJEXT) +plugin_test_LDADD = $(LDADD) +plugin_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(am__DEPENDENCIES_1) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +query_test_SOURCES = query_test.c +query_test_OBJECTS = query_test.$(OBJEXT) +query_test_LDADD = $(LDADD) +query_test_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(am__DEPENDENCIES_1) $(top_builddir)/tests/libtest/libtest.la \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/listenlist_test.Po \ + ./$(DEPDIR)/notify_test.Po ./$(DEPDIR)/plugin_test.Po \ + ./$(DEPDIR)/query_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = listenlist_test.c notify_test.c plugin_test.c query_test.c +DIST_SOURCES = listenlist_test.c notify_test.c plugin_test.c \ + query_test.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.tests \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LATEXMK = @LATEXMK@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XELATEX = @XELATEX@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -I$(top_srcdir)/tests/include $(TEST_CFLAGS) +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBUV_CFLAGS) -I$(top_srcdir)/lib/isc \ + -I$(top_srcdir)/lib/dns $(CMOCKA_CFLAGS) \ + -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) $(LIBUV_LIBS) \ + $(top_builddir)/tests/libtest/libtest.la $(CMOCKA_LIBS) +LIBISC_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +LIBIRS_CFLAGS = \ + -I$(top_srcdir)/lib/irs/include + +LIBIRS_LIBS = \ + $(top_builddir)/lib/irs/libirs.la + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +LIBBIND9_CFLAGS = \ + -I$(top_srcdir)/lib/bind9/include + +LIBBIND9_LIBS = \ + $(top_builddir)/lib/bind9/libbind9.la + +EXTRA_DIST = testdata +@HAVE_CMOCKA_TRUE@TESTS = $(check_PROGRAMS) +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/ns/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/ns/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(top_srcdir)/Makefile.tests $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +listenlist_test$(EXEEXT): $(listenlist_test_OBJECTS) $(listenlist_test_DEPENDENCIES) $(EXTRA_listenlist_test_DEPENDENCIES) + @rm -f listenlist_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(listenlist_test_OBJECTS) $(listenlist_test_LDADD) $(LIBS) + +notify_test$(EXEEXT): $(notify_test_OBJECTS) $(notify_test_DEPENDENCIES) $(EXTRA_notify_test_DEPENDENCIES) + @rm -f notify_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(notify_test_OBJECTS) $(notify_test_LDADD) $(LIBS) + +plugin_test$(EXEEXT): $(plugin_test_OBJECTS) $(plugin_test_DEPENDENCIES) $(EXTRA_plugin_test_DEPENDENCIES) + @rm -f plugin_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(plugin_test_OBJECTS) $(plugin_test_LDADD) $(LIBS) + +query_test$(EXEEXT): $(query_test_OBJECTS) $(query_test_DEPENDENCIES) $(EXTRA_query_test_DEPENDENCIES) + @rm -f query_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(query_test_OBJECTS) $(query_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listenlist_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +listenlist_test.log: listenlist_test$(EXEEXT) + @p='listenlist_test$(EXEEXT)'; \ + b='listenlist_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +notify_test.log: notify_test$(EXEEXT) + @p='notify_test$(EXEEXT)'; \ + b='notify_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +plugin_test.log: plugin_test$(EXEEXT) + @p='plugin_test$(EXEEXT)'; \ + b='plugin_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +query_test.log: query_test$(EXEEXT) + @p='query_test$(EXEEXT)'; \ + b='query_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/listenlist_test.Po + -rm -f ./$(DEPDIR)/notify_test.Po + -rm -f ./$(DEPDIR)/plugin_test.Po + -rm -f ./$(DEPDIR)/query_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/listenlist_test.Po + -rm -f ./$(DEPDIR)/notify_test.Po + -rm -f ./$(DEPDIR)/plugin_test.Po + -rm -f ./$(DEPDIR)/query_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am recheck tags tags-am test-am test-local \ + uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +unit-local: check + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/ns/listenlist_test.c b/tests/ns/listenlist_test.c new file mode 100644 index 0000000..53d5783 --- /dev/null +++ b/tests/ns/listenlist_test.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/list.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/util.h> + +#include <dns/acl.h> + +#include <ns/listenlist.h> + +#include <tests/ns.h> + +static int +_setup(void **state) { + isc__nm_force_tid(0); + + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + isc__nm_force_tid(-1); + + teardown_managers(state); + + return (0); +} + +/* test that ns_listenlist_default() works */ +ISC_RUN_TEST_IMPL(ns_listenlist_default) { + isc_result_t result; + in_port_t port = 5300 + isc_random8(); + ns_listenlist_t *list = NULL; + ns_listenelt_t *elt; + int count; + + UNUSED(state); + + result = ns_listenlist_default(mctx, port, false, AF_INET, &list); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(list); + + assert_false(ISC_LIST_EMPTY(list->elts)); + + count = 0; + elt = ISC_LIST_HEAD(list->elts); + while (elt != NULL) { + ns_listenelt_t *next = ISC_LIST_NEXT(elt, link); + dns_acl_t *acl = NULL; + + dns_acl_attach(elt->acl, &acl); + ISC_LIST_UNLINK(list->elts, elt, link); + ns_listenelt_destroy(elt); + elt = next; + + assert_true(dns_acl_isnone(acl)); + dns_acl_detach(&acl); + count++; + } + + assert_true(ISC_LIST_EMPTY(list->elts)); + assert_int_equal(count, 1); + + ns_listenlist_detach(&list); + + result = ns_listenlist_default(mctx, port, true, AF_INET, &list); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(ISC_LIST_EMPTY(list->elts)); + + /* This time just use ns_listenlist_detach() to destroy elements */ + count = 0; + elt = ISC_LIST_HEAD(list->elts); + while (elt != NULL) { + ns_listenelt_t *next = ISC_LIST_NEXT(elt, link); + assert_true(dns_acl_isany(elt->acl)); + elt = next; + count++; + } + + assert_int_equal(count, 1); + + ns_listenlist_detach(&list); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(ns_listenlist_default, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/ns/notify_test.c b/tests/ns/notify_test.c new file mode 100644 index 0000000..1b962e3 --- /dev/null +++ b/tests/ns/notify_test.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/event.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/thread.h> +#include <isc/util.h> + +#include <dns/acl.h> +#include <dns/rcode.h> +#include <dns/view.h> + +#include <ns/client.h> +#include <ns/notify.h> + +#include <tests/dns.h> +#include <tests/ns.h> + +static int +setup_test(void **state) { + isc__nm_force_tid(0); + return (setup_server(state)); +} + +static int +teardown_test(void **state) { + isc__nm_force_tid(-1); + return (teardown_server(state)); +} + +static void +check_response(isc_buffer_t *buf) { + isc_result_t result; + dns_message_t *message = NULL; + char rcodebuf[20]; + isc_buffer_t b; + + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message); + + result = dns_message_parse(message, buf, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&b, rcodebuf, sizeof(rcodebuf)); + result = dns_rcode_totext(message->rcode, &b); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_int_equal(message->rcode, dns_rcode_noerror); + + dns_message_detach(&message); +} + +/* test ns_notify_start() */ +ISC_RUN_TEST_IMPL(ns_notify_start) { + isc_result_t result; + ns_client_t *client = NULL; + isc_nmhandle_t *handle = NULL; + dns_message_t *nmsg = NULL; + unsigned char ndata[4096]; + isc_buffer_t nbuf; + size_t nsize; + + UNUSED(state); + + result = ns_test_getclient(NULL, false, &client); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_makeview("view", false, &client->view); + assert_int_equal(result, ISC_R_SUCCESS); + + result = ns_test_serve_zone("example.com", + TESTS_DIR "/testdata/notify/zone1.db", + client->view); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Create a NOTIFY message by parsing a file in testdata. + * (XXX: use better message mocking method when available.) + */ + + result = ns_test_getdata(TESTS_DIR "/testdata/notify/notify1.msg", + ndata, sizeof(ndata), &nsize); + assert_int_equal(result, ISC_R_SUCCESS); + isc_buffer_init(&nbuf, ndata, nsize); + isc_buffer_add(&nbuf, nsize); + + dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &nmsg); + + result = dns_message_parse(nmsg, &nbuf, 0); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Set up client object with this message and test the NOTIFY + * handler. + */ + if (client->message != NULL) { + dns_message_detach(&client->message); + } + client->message = nmsg; + nmsg = NULL; + client->sendcb = check_response; + ns_notify_start(client, client->handle); + + /* + * Clean up + */ + ns_test_cleanup_zone(); + + handle = client->handle; + isc_nmhandle_detach(&client->handle); + isc_nmhandle_detach(&handle); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY_CUSTOM(ns_notify_start, setup_test, teardown_test) +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/ns/plugin_test.c b/tests/ns/plugin_test.c new file mode 100644 index 0000000..24d021e --- /dev/null +++ b/tests/ns/plugin_test.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <limits.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/attributes.h> +#include <isc/dir.h> +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/types.h> +#include <isc/util.h> + +noreturn void +_fail(const char *const file, const int line); + +#include <ns/hooks.h> + +#include <tests/ns.h> + +/*% + * Structure containing parameters for run_full_path_test(). + */ +typedef struct { + const ns_test_id_t id; /* libns test identifier */ + const char *input; /* source string - plugin name or path + * */ + size_t output_size; /* size of target char array to + * allocate */ + isc_result_t result; /* expected return value */ + const char *output; /* expected output string */ +} ns_plugin_expandpath_test_params_t; + +/*% + * Perform a single ns_plugin_expandpath() check using given parameters. + */ +static void +run_full_path_test(const ns_plugin_expandpath_test_params_t *test, + void **state) { + char **target = (char **)state; + isc_result_t result; + + REQUIRE(test != NULL); + REQUIRE(test->id.description != NULL); + REQUIRE(test->input != NULL); + REQUIRE(test->result != ISC_R_SUCCESS || test->output != NULL); + + /* + * Prepare a target buffer of given size. Store it in 'state' so that + * it can get cleaned up by _teardown() if the test fails. + */ + *target = isc_mem_allocate(mctx, test->output_size); + + /* + * Call ns_plugin_expandpath(). + */ + result = ns_plugin_expandpath(test->input, *target, test->output_size); + + /* + * Check return value. + */ + if (result != test->result) { + fail_msg("# test \"%s\" on line %d: " + "expected result %d (%s), got %d (%s)", + test->id.description, test->id.lineno, test->result, + isc_result_totext(test->result), result, + isc_result_totext(result)); + } + + /* + * Check output string if return value indicates success. + */ + if (result == ISC_R_SUCCESS && strcmp(*target, test->output) != 0) { + fail_msg("# test \"%s\" on line %d: " + "expected output \"%s\", got \"%s\"", + test->id.description, test->id.lineno, test->output, + *target); + } + + isc_mem_free(mctx, *target); +} + +/* test ns_plugin_expandpath() */ +ISC_RUN_TEST_IMPL(ns_plugin_expandpath) { + size_t i; + + const ns_plugin_expandpath_test_params_t tests[] = { + { + NS_TEST_ID("correct use with an absolute path"), + .input = "/usr/lib/named/foo.so", + .output_size = PATH_MAX, + .result = ISC_R_SUCCESS, + .output = "/usr/lib/named/foo.so", + }, + { + NS_TEST_ID("correct use with a relative path"), + .input = "../../foo.so", + .output_size = PATH_MAX, + .result = ISC_R_SUCCESS, + .output = "../../foo.so", + }, + { + NS_TEST_ID("correct use with a filename"), + .input = "foo.so", + .output_size = PATH_MAX, + .result = ISC_R_SUCCESS, + .output = NAMED_PLUGINDIR "/foo.so", + }, + { + NS_TEST_ID("no space at all in target buffer"), + .input = "/usr/lib/named/foo.so", + .output_size = 0, + .result = ISC_R_NOSPACE, + }, + { + NS_TEST_ID("target buffer too small to fit input"), + .input = "/usr/lib/named/foo.so", + .output_size = 1, + .result = ISC_R_NOSPACE, + }, + { + NS_TEST_ID("target buffer too small to fit NULL byte"), + .input = "/foo.so", + .output_size = 7, + .result = ISC_R_NOSPACE, + }, + { + NS_TEST_ID("target buffer too small to fit full path"), + .input = "foo.so", + .output_size = 7, + .result = ISC_R_NOSPACE, + }, + }; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + run_full_path_test(&tests[i], state); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(ns_plugin_expandpath, setup_managers, teardown_managers) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN diff --git a/tests/ns/query_test.c b/tests/ns/query_test.c new file mode 100644 index 0000000..5bea01a --- /dev/null +++ b/tests/ns/query_test.c @@ -0,0 +1,1500 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <sched.h> /* IWYU pragma: keep */ +#include <setjmp.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/quota.h> +#include <isc/util.h> + +#include <dns/badcache.h> +#include <dns/view.h> +#include <dns/zone.h> + +#include <ns/client.h> +#include <ns/events.h> +#include <ns/hooks.h> +#include <ns/query.h> +#include <ns/server.h> +#include <ns/stats.h> + +#include <tests/ns.h> + +static int +setup_test(void **state) { + isc__nm_force_tid(0); + setup_server(state); + return (0); +} + +static int +teardown_test(void **state) { + isc__nm_force_tid(-1); + teardown_server(state); + return (0); +} + +/* can be used for client->sendcb to avoid disruption on sending a response */ +static void +send_noop(isc_buffer_t *buffer) { + UNUSED(buffer); +} + +/***** +***** ns__query_sfcache() tests +*****/ + +/*% + * Structure containing parameters for ns__query_sfcache_test(). + */ +typedef struct { + const ns_test_id_t id; /* libns test identifier */ + unsigned int qflags; /* query flags */ + bool cache_entry_present; /* whether a SERVFAIL + * cache entry + * matching the query + * should be + * present */ + uint32_t cache_entry_flags; /* NS_FAILCACHE_* flags to + * set for + * the SERVFAIL cache entry + * */ + bool servfail_expected; /* whether a cached + * SERVFAIL is + * expected to be returned + * */ +} ns__query_sfcache_test_params_t; + +/*% + * Perform a single ns__query_sfcache() check using given parameters. + */ +static void +run_sfcache_test(const ns__query_sfcache_test_params_t *test) { + ns_hooktable_t *query_hooks = NULL; + query_ctx_t *qctx = NULL; + isc_result_t result; + const ns_hook_t hook = { + .action = ns_test_hook_catch_call, + }; + + REQUIRE(test != NULL); + REQUIRE(test->id.description != NULL); + REQUIRE(test->cache_entry_present || test->cache_entry_flags == 0); + + /* + * Interrupt execution if ns_query_done() is called. + */ + + ns_hooktable_create(mctx, &query_hooks); + ns_hook_add(query_hooks, mctx, NS_QUERY_DONE_BEGIN, &hook); + ns__hook_table = query_hooks; + + /* + * Construct a query context for a ./NS query with given flags. + */ + { + const ns_test_qctx_create_params_t qctx_params = { + .qname = ".", + .qtype = dns_rdatatype_ns, + .qflags = test->qflags, + .with_cache = true, + }; + + result = ns_test_qctx_create(&qctx_params, &qctx); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* + * If this test wants a SERVFAIL cache entry matching the query to + * exist, create it. + */ + if (test->cache_entry_present) { + isc_interval_t hour; + isc_time_t expire; + + isc_interval_set(&hour, 3600, 0); + result = isc_time_nowplusinterval(&expire, &hour); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_badcache_add(qctx->client->view->failcache, dns_rootname, + dns_rdatatype_ns, true, + test->cache_entry_flags, &expire); + } + + /* + * Check whether ns__query_sfcache() behaves as expected. + */ + ns__query_sfcache(qctx); + + if (test->servfail_expected) { + if (qctx->result != DNS_R_SERVFAIL) { + fail_msg("# test \"%s\" on line %d: " + "expected SERVFAIL, got %s", + test->id.description, test->id.lineno, + isc_result_totext(qctx->result)); + } + } else { + if (qctx->result != ISC_R_SUCCESS) { + fail_msg("# test \"%s\" on line %d: " + "expected success, got %s", + test->id.description, test->id.lineno, + isc_result_totext(qctx->result)); + } + } + + /* + * Clean up. + */ + ns_test_qctx_destroy(&qctx); + ns_hooktable_free(mctx, (void **)&query_hooks); +} + +/* test ns__query_sfcache() */ +ISC_RUN_TEST_IMPL(ns_query_sfcache) { + size_t i; + + const ns__query_sfcache_test_params_t tests[] = { + /* + * Sanity check for an empty SERVFAIL cache. + */ + { + NS_TEST_ID("query: RD=1, CD=0; cache: empty"), + .qflags = DNS_MESSAGEFLAG_RD, + .cache_entry_present = false, + .servfail_expected = false, + }, + /* + * Query: RD=1, CD=0. Cache entry: CD=0. Should SERVFAIL. + */ + { + NS_TEST_ID("query: RD=1, CD=0; cache: CD=0"), + .qflags = DNS_MESSAGEFLAG_RD, + .cache_entry_present = true, + .cache_entry_flags = 0, + .servfail_expected = true, + }, + /* + * Query: RD=1, CD=1. Cache entry: CD=0. Should not SERVFAIL: + * failed validation should not influence CD=1 queries. + */ + { + NS_TEST_ID("query: RD=1, CD=1; cache: CD=0"), + .qflags = DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_CD, + .cache_entry_present = true, + .cache_entry_flags = 0, + .servfail_expected = false, + }, + /* + * Query: RD=1, CD=1. Cache entry: CD=1. Should SERVFAIL: + * SERVFAIL responses elicited by CD=1 queries can be + * "replayed" for other CD=1 queries during the lifetime of the + * SERVFAIL cache entry. + */ + { + NS_TEST_ID("query: RD=1, CD=1; cache: CD=1"), + .qflags = DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_CD, + .cache_entry_present = true, + .cache_entry_flags = NS_FAILCACHE_CD, + .servfail_expected = true, + }, + /* + * Query: RD=1, CD=0. Cache entry: CD=1. Should SERVFAIL: if + * a CD=1 query elicited a SERVFAIL, a CD=0 query for the same + * QNAME and QTYPE will SERVFAIL as well. + */ + { + NS_TEST_ID("query: RD=1, CD=0; cache: CD=1"), + .qflags = DNS_MESSAGEFLAG_RD, + .cache_entry_present = true, + .cache_entry_flags = NS_FAILCACHE_CD, + .servfail_expected = true, + }, + /* + * Query: RD=0, CD=0. Cache entry: CD=0. Should not SERVFAIL + * despite a matching entry being present as the SERVFAIL cache + * should not be consulted for non-recursive queries. + */ + { + NS_TEST_ID("query: RD=0, CD=0; cache: CD=0"), + .qflags = 0, + .cache_entry_present = true, + .cache_entry_flags = 0, + .servfail_expected = false, + }, + }; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + run_sfcache_test(&tests[i]); + } +} + +/***** +***** ns__query_start() tests +*****/ + +/*% + * Structure containing parameters for ns__query_start_test(). + */ +typedef struct { + const ns_test_id_t id; /* libns test identifier */ + const char *qname; /* QNAME */ + dns_rdatatype_t qtype; /* QTYPE */ + unsigned int qflags; /* query flags */ + bool disable_name_checks; /* if set to true, owner + * name + * checks will + * be disabled for the + * view created + * */ + bool recursive_service; /* if set to true, the view + * created will + * have a cache + * database + * attached */ + const char *auth_zone_origin; /* origin name of the zone + * the + * created view will be + * authoritative for */ + const char *auth_zone_path; /* path to load the + * authoritative + * zone from */ + enum { /* expected result: */ + NS__QUERY_START_R_INVALID, + NS__QUERY_START_R_REFUSE, /* query should be REFUSED */ + NS__QUERY_START_R_CACHE, /* query should be answered from + * cache */ + NS__QUERY_START_R_AUTH, /* query should be answered using + * authoritative data */ + } expected_result; +} ns__query_start_test_params_t; + +/*% + * Perform a single ns__query_start() check using given parameters. + */ +static void +run_start_test(const ns__query_start_test_params_t *test) { + ns_hooktable_t *query_hooks = NULL; + query_ctx_t *qctx = NULL; + isc_result_t result; + const ns_hook_t hook = { + .action = ns_test_hook_catch_call, + }; + + REQUIRE(test != NULL); + REQUIRE(test->id.description != NULL); + REQUIRE((test->auth_zone_origin == NULL && + test->auth_zone_path == NULL) || + (test->auth_zone_origin != NULL && + test->auth_zone_path != NULL)); + + /* + * Interrupt execution if query_lookup() or ns_query_done() is called. + */ + + ns_hooktable_create(mctx, &query_hooks); + ns_hook_add(query_hooks, mctx, NS_QUERY_LOOKUP_BEGIN, &hook); + ns_hook_add(query_hooks, mctx, NS_QUERY_DONE_BEGIN, &hook); + ns__hook_table = query_hooks; + + /* + * Construct a query context using the supplied parameters. + */ + { + const ns_test_qctx_create_params_t qctx_params = { + .qname = test->qname, + .qtype = test->qtype, + .qflags = test->qflags, + .with_cache = test->recursive_service, + }; + result = ns_test_qctx_create(&qctx_params, &qctx); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* + * Enable view->checknames by default, disable if requested. + */ + qctx->client->view->checknames = !test->disable_name_checks; + + /* + * Load zone from file and attach it to the client's view, if + * requested. + */ + if (test->auth_zone_path != NULL) { + result = ns_test_serve_zone(test->auth_zone_origin, + test->auth_zone_path, + qctx->client->view); + assert_int_equal(result, ISC_R_SUCCESS); + } + + /* + * Check whether ns__query_start() behaves as expected. + */ + ns__query_start(qctx); + + switch (test->expected_result) { + case NS__QUERY_START_R_REFUSE: + if (qctx->result != DNS_R_REFUSED) { + fail_msg("# test \"%s\" on line %d: " + "expected REFUSED, got %s", + test->id.description, test->id.lineno, + isc_result_totext(qctx->result)); + } + if (qctx->zone != NULL) { + fail_msg("# test \"%s\" on line %d: " + "no zone was expected to be attached to " + "query context, but some was", + test->id.description, test->id.lineno); + } + if (qctx->db != NULL) { + fail_msg("# test \"%s\" on line %d: " + "no database was expected to be attached to " + "query context, but some was", + test->id.description, test->id.lineno); + } + break; + case NS__QUERY_START_R_CACHE: + if (qctx->result != ISC_R_SUCCESS) { + fail_msg("# test \"%s\" on line %d: " + "expected success, got %s", + test->id.description, test->id.lineno, + isc_result_totext(qctx->result)); + } + if (qctx->zone != NULL) { + fail_msg("# test \"%s\" on line %d: " + "no zone was expected to be attached to " + "query context, but some was", + test->id.description, test->id.lineno); + } + if (qctx->db == NULL || qctx->db != qctx->client->view->cachedb) + { + fail_msg("# test \"%s\" on line %d: " + "cache database was expected to be " + "attached to query context, but it was not", + test->id.description, test->id.lineno); + } + break; + case NS__QUERY_START_R_AUTH: + if (qctx->result != ISC_R_SUCCESS) { + fail_msg("# test \"%s\" on line %d: " + "expected success, got %s", + test->id.description, test->id.lineno, + isc_result_totext(qctx->result)); + } + if (qctx->zone == NULL) { + fail_msg("# test \"%s\" on line %d: " + "a zone was expected to be attached to query " + "context, but it was not", + test->id.description, test->id.lineno); + } + if (qctx->db == qctx->client->view->cachedb) { + fail_msg("# test \"%s\" on line %d: " + "cache database was not expected to be " + "attached to query context, but it is", + test->id.description, test->id.lineno); + } + break; + case NS__QUERY_START_R_INVALID: + fail_msg("# test \"%s\" on line %d has no expected result set", + test->id.description, test->id.lineno); + break; + default: + UNREACHABLE(); + } + + /* + * Clean up. + */ + if (test->auth_zone_path != NULL) { + ns_test_cleanup_zone(); + } + ns_test_qctx_destroy(&qctx); + ns_hooktable_free(mctx, (void **)&query_hooks); +} + +/* test ns__query_start() */ +ISC_RUN_TEST_IMPL(ns_query_start) { + size_t i; + + const ns__query_start_test_params_t tests[] = { + /* + * Recursive foo/A query to a server without recursive service + * and no zones configured. Query should be REFUSED. + */ + { + NS_TEST_ID("foo/A, no cache, no auth"), + .qname = "foo", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = false, + .expected_result = NS__QUERY_START_R_REFUSE, + }, + /* + * Recursive foo/A query to a server with recursive service and + * no zones configured. Query should be answered from cache. + */ + { + NS_TEST_ID("foo/A, cache, no auth"), + .qname = "foo", + .qtype = dns_rdatatype_a, + .recursive_service = true, + .expected_result = NS__QUERY_START_R_CACHE, + }, + /* + * Recursive foo/A query to a server with recursive service and + * zone "foo" configured. Query should be answered from + * authoritative data. + */ + { + NS_TEST_ID("foo/A, RD=1, cache, auth for foo"), + .qname = "foo", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_AUTH, + }, + /* + * Recursive bar/A query to a server without recursive service + * and zone "foo" configured. Query should be REFUSED. + */ + { + NS_TEST_ID("bar/A, RD=1, no cache, auth for foo"), + .qname = "bar", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = false, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_REFUSE, + }, + /* + * Recursive bar/A query to a server with recursive service and + * zone "foo" configured. Query should be answered from + * cache. + */ + { + NS_TEST_ID("bar/A, RD=1, cache, auth for foo"), + .qname = "bar", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_CACHE, + }, + /* + * Recursive bar.foo/DS query to a server with recursive + * service and zone "foo" configured. Query should be answered + * from authoritative data. + */ + { + NS_TEST_ID("bar.foo/DS, RD=1, cache, auth for foo"), + .qname = "bar.foo", + .qtype = dns_rdatatype_ds, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_AUTH, + }, + /* + * Non-recursive bar.foo/DS query to a server with recursive + * service and zone "foo" configured. Query should be answered + * from authoritative data. + */ + { + NS_TEST_ID("bar.foo/DS, RD=0, cache, auth for foo"), + .qname = "bar.foo", + .qtype = dns_rdatatype_ds, + .qflags = 0, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_AUTH, + }, + /* + * Recursive foo/DS query to a server with recursive service + * and zone "foo" configured. Query should be answered from + * cache. + */ + { + NS_TEST_ID("foo/DS, RD=1, cache, auth for foo"), + .qname = "foo", + .qtype = dns_rdatatype_ds, + .qflags = DNS_MESSAGEFLAG_RD, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_CACHE, + }, + /* + * Non-recursive foo/DS query to a server with recursive + * service and zone "foo" configured. Query should be answered + * from authoritative data. + */ + { + NS_TEST_ID("foo/DS, RD=0, cache, auth for foo"), + .qname = "foo", + .qtype = dns_rdatatype_ds, + .qflags = 0, + .recursive_service = true, + .auth_zone_origin = "foo", + .auth_zone_path = TESTS_DIR "/testdata/query/foo.db", + .expected_result = NS__QUERY_START_R_AUTH, + }, + /* + * Recursive _foo/A query to a server with recursive service, + * no zones configured and owner name checks disabled. Query + * should be answered from cache. + */ + { + NS_TEST_ID("_foo/A, cache, no auth, name checks off"), + .qname = "_foo", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .disable_name_checks = true, + .recursive_service = true, + .expected_result = NS__QUERY_START_R_CACHE, + }, + /* + * Recursive _foo/A query to a server with recursive service, + * no zones configured and owner name checks enabled. Query + * should be REFUSED. + */ + { + NS_TEST_ID("_foo/A, cache, no auth, name checks on"), + .qname = "_foo", + .qtype = dns_rdatatype_a, + .qflags = DNS_MESSAGEFLAG_RD, + .disable_name_checks = false, + .recursive_service = true, + .expected_result = NS__QUERY_START_R_REFUSE, + }, + }; + + UNUSED(state); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + run_start_test(&tests[i]); + } +} + +/***** +***** tests for ns_query_hookasync(). +*****/ + +/*% + * Structure containing parameters for ns__query_hookasync_test(). + */ +typedef struct { + const ns_test_id_t id; /* libns test identifier */ + ns_hookpoint_t hookpoint; /* hook point specified for resume */ + ns_hookpoint_t hookpoint2; /* expected hook point used after resume */ + ns_hook_action_t action; /* action for the hook point */ + isc_result_t start_result; /* result of 'runasync' */ + bool quota_ok; /* true if recursion quota should be okay */ + bool do_cancel; /* true if query should be canceled + * in test */ +} ns__query_hookasync_test_params_t; + +/* Data structure passed from tests to hooks */ +typedef struct hookasync_data { + bool async; /* true if in a hook-triggered + * asynchronous process */ + bool canceled; /* true if the query has been canceled */ + isc_result_t start_result; /* result of 'runasync' */ + ns_hook_resevent_t *rev; /* resume event sent on completion */ + query_ctx_t qctx; /* shallow copy of qctx passed to hook */ + ns_hookpoint_t hookpoint; /* specifies where to resume */ + ns_hookpoint_t lasthookpoint; /* remember the last hook point called */ +} hookasync_data_t; + +/* + * 'destroy' callback of hook recursion ctx. + * The dynamically allocated context will be freed here, thereby proving + * this is actually called; otherwise tests would fail due to memory leak. + */ +static void +destroy_hookactx(ns_hookasync_t **ctxp) { + ns_hookasync_t *ctx = *ctxp; + + *ctxp = NULL; + isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); +} + +/* 'cancel' callback of hook recursion ctx. */ +static void +cancel_hookactx(ns_hookasync_t *ctx) { + /* Mark the hook data so the test can confirm this is called. */ + ((hookasync_data_t *)ctx->private)->canceled = true; +} + +/* 'runasync' callback passed to ns_query_hookasync */ +static isc_result_t +test_hookasync(query_ctx_t *qctx, isc_mem_t *memctx, void *arg, + isc_task_t *task, isc_taskaction_t action, void *evarg, + ns_hookasync_t **ctxp) { + hookasync_data_t *asdata = arg; + ns_hookasync_t *ctx = NULL; + ns_hook_resevent_t *rev = NULL; + + if (asdata->start_result != ISC_R_SUCCESS) { + return (asdata->start_result); + } + + ctx = isc_mem_get(memctx, sizeof(*ctx)); + rev = (ns_hook_resevent_t *)isc_event_allocate( + memctx, task, NS_EVENT_HOOKASYNCDONE, action, evarg, + sizeof(*rev)); + + rev->hookpoint = asdata->hookpoint; + rev->origresult = DNS_R_NXDOMAIN; + rev->saved_qctx = qctx; + rev->ctx = ctx; + asdata->rev = rev; + + *ctx = (ns_hookasync_t){ .private = asdata }; + isc_mem_attach(memctx, &ctx->mctx); + ctx->destroy = destroy_hookactx; + ctx->cancel = cancel_hookactx; + + *ctxp = ctx; + return (ISC_R_SUCCESS); +} + +/* + * Main logic for hook actions. + * 'hookpoint' should identify the point that calls the hook. It will be + * remembered in the hook data, so that the test can confirm which hook point + * was last used. + */ +static ns_hookresult_t +hook_async_common(void *arg, void *data, isc_result_t *resultp, + ns_hookpoint_t hookpoint) { + query_ctx_t *qctx = arg; + hookasync_data_t *asdata = data; + isc_result_t result; + + asdata->qctx = *qctx; /* remember passed ctx for inspection */ + asdata->lasthookpoint = hookpoint; /* ditto */ + + if (!asdata->async) { + /* Initial call to the hook; start recursion */ + result = ns_query_hookasync(qctx, test_hookasync, asdata); + if (result == ISC_R_SUCCESS) { + asdata->async = true; + } + } else { + /* + * Resume from the completion of async event. + * fetchhandle should have been detached so that we can start + * another async event or DNS recursive resolution. + */ + INSIST(qctx->client->fetchhandle == NULL); + asdata->async = false; + switch (hookpoint) { + case NS_QUERY_GOT_ANSWER_BEGIN: + case NS_QUERY_NODATA_BEGIN: + case NS_QUERY_NXDOMAIN_BEGIN: + case NS_QUERY_NCACHE_BEGIN: + INSIST(*resultp == DNS_R_NXDOMAIN); + break; + default:; + } + } + + *resultp = ISC_R_UNSET; + return (NS_HOOK_RETURN); +} + +static ns_hookresult_t +hook_async_query_setup(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_SETUP)); +} + +static ns_hookresult_t +hook_async_query_start_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_START_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_lookup_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_LOOKUP_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_resume_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_RESUME_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_got_answer_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_GOT_ANSWER_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_respond_any_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_RESPOND_ANY_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_addanswer_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_ADDANSWER_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_notfound_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_NOTFOUND_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_prep_delegation_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_PREP_DELEGATION_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_zone_delegation_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_ZONE_DELEGATION_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_delegation_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_DELEGATION_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_delegation_recurse_begin(void *arg, void *data, + isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_DELEGATION_RECURSE_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_nodata_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_NODATA_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_nxdomain_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_NXDOMAIN_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_ncache_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_NCACHE_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_cname_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_CNAME_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_dname_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_DNAME_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_respond_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_RESPOND_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_response_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, + NS_QUERY_PREP_RESPONSE_BEGIN)); +} + +static ns_hookresult_t +hook_async_query_done_begin(void *arg, void *data, isc_result_t *resultp) { + return (hook_async_common(arg, data, resultp, NS_QUERY_DONE_BEGIN)); +} + +/* + * hook on destroying actx. Can't be used for async event, but we use this + * to remember the qctx at that point. + */ +static ns_hookresult_t +ns_test_qctx_destroy_hook(void *arg, void *data, isc_result_t *resultp) { + query_ctx_t *qctx = arg; + hookasync_data_t *asdata = data; + + asdata->qctx = *qctx; /* remember passed ctx for inspection */ + *resultp = ISC_R_UNSET; + return (NS_HOOK_CONTINUE); +} + +static void +run_hookasync_test(const ns__query_hookasync_test_params_t *test) { + query_ctx_t *qctx = NULL; + isc_result_t result; + hookasync_data_t asdata = { + .async = false, + .canceled = false, + .start_result = test->start_result, + .hookpoint = test->hookpoint, + }; + const ns_hook_t testhook = { + .action = test->action, + .action_data = &asdata, + }; + const ns_hook_t destroyhook = { + .action = ns_test_qctx_destroy_hook, + .action_data = &asdata, + }; + isc_quota_t *quota = NULL; + isc_statscounter_t srvfail_cnt; + bool expect_servfail = false; + + /* + * Prepare hooks. We always begin with ns__query_start for simplicity. + * Its action will specify various different resume points (unusual + * in practice, but that's fine for the testing purpose). + */ + ns__hook_table = NULL; + ns_hooktable_create(mctx, &ns__hook_table); + ns_hook_add(ns__hook_table, mctx, NS_QUERY_START_BEGIN, &testhook); + if (test->hookpoint2 != NS_QUERY_START_BEGIN) { + /* + * unless testing START_BEGIN itself, specify the hook for the + * expected resume point, too. + */ + ns_hook_add(ns__hook_table, mctx, test->hookpoint2, &testhook); + } + ns_hook_add(ns__hook_table, mctx, NS_QUERY_QCTX_DESTROYED, + &destroyhook); + + { + const ns_test_qctx_create_params_t qctx_params = { + .qname = "test.example.com", + .qtype = dns_rdatatype_aaaa, + }; + result = ns_test_qctx_create(&qctx_params, &qctx); + INSIST(result == ISC_R_SUCCESS); + qctx->client->sendcb = send_noop; + } + + /* + * Set recursion quota to the lowest possible value, then make it full + * if we want to exercise a quota failure case. + */ + isc_quota_max(&sctx->recursionquota, 1); + if (!test->quota_ok) { + result = isc_quota_attach(&sctx->recursionquota, "a); + INSIST(result == ISC_R_SUCCESS); + } + + /* Remember SERVFAIL counter */ + srvfail_cnt = ns_stats_get_counter(qctx->client->sctx->nsstats, + ns_statscounter_servfail); + + /* + * If the query has been canceled, or async event didn't succeed, + * SERVFAIL will have to be sent. In this case we need to have + * 'reqhandle' attach to the client's handle as it's detached in + * query_error. + */ + if (test->start_result != ISC_R_SUCCESS || !test->quota_ok || + test->do_cancel) + { + expect_servfail = true; + isc_nmhandle_attach(qctx->client->handle, + &qctx->client->reqhandle); + } + + /* + * Emulate query handling from query_start. + * Specified hook should be called. + */ + qctx->client->state = NS_CLIENTSTATE_WORKING; + result = ns__query_start(qctx); + INSIST(result == ISC_R_UNSET); + + /* + * hook-triggered async event should be happening unless it hits + * recursion quota limit or 'runasync' callback fails. + */ + INSIST(asdata.async == + (test->quota_ok && test->start_result == ISC_R_SUCCESS)); + + /* + * Emulate cancel if so specified. + * The cancel callback should be called. + */ + if (test->do_cancel) { + ns_query_cancel(qctx->client); + } + INSIST(asdata.canceled == test->do_cancel); + + /* If async event has started, manually invoke the 'done' event. */ + if (asdata.async) { + qctx->client->now = 0; /* set to sentinel before resume */ + asdata.rev->ev_action(asdata.rev->ev_sender, + (isc_event_t *)asdata.rev); + + /* Confirm necessary cleanup has been performed. */ + INSIST(qctx->client->query.hookactx == NULL); + INSIST(qctx->client->state == NS_CLIENTSTATE_WORKING); + INSIST(qctx->client->recursionquota == NULL); + INSIST(ns_stats_get_counter(qctx->client->sctx->nsstats, + ns_statscounter_recursclients) == + 0); + INSIST(!ISC_LINK_LINKED(qctx->client, rlink)); + if (!test->do_cancel) { + /* + * In the normal case the client's timestamp is updated + * and the query handling has been resumed from the + * expected point. + */ + INSIST(qctx->client->now != 0); + INSIST(asdata.lasthookpoint == test->hookpoint2); + } + } else { + INSIST(qctx->client->query.hookactx == NULL); + } + + /* + * Confirm SERVFAIL has been sent if it was expected. + * Also, the last-generated qctx should have detach_client being true. + */ + if (expect_servfail) { + INSIST(ns_stats_get_counter(qctx->client->sctx->nsstats, + ns_statscounter_servfail) == + srvfail_cnt + 1); + if (test->do_cancel) { + /* qctx was created on resume and copied in hook */ + INSIST(asdata.qctx.detach_client); + } else { + INSIST(qctx->detach_client); + } + } + + /* + * Cleanup. Note that we've kept 'qctx' until now; otherwise + * qctx->client may have been invalidated while we still need it. + */ + ns_test_qctx_destroy(&qctx); + ns_hooktable_free(mctx, (void **)&ns__hook_table); + if (quota != NULL) { + isc_quota_detach("a); + } +} + +ISC_RUN_TEST_IMPL(ns_query_hookasync) { + size_t i; + + UNUSED(state); + + const ns__query_hookasync_test_params_t tests[] = { + { + NS_TEST_ID("normal case"), + NS_QUERY_START_BEGIN, + NS_QUERY_START_BEGIN, + hook_async_query_start_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("quota fail"), + NS_QUERY_START_BEGIN, + NS_QUERY_START_BEGIN, + hook_async_query_start_begin, + ISC_R_SUCCESS, + false, + false, + }, + { + NS_TEST_ID("start fail"), + NS_QUERY_START_BEGIN, + NS_QUERY_START_BEGIN, + hook_async_query_start_begin, + ISC_R_FAILURE, + true, + false, + }, + { + NS_TEST_ID("query cancel"), + NS_QUERY_START_BEGIN, + NS_QUERY_START_BEGIN, + hook_async_query_start_begin, + ISC_R_SUCCESS, + true, + true, + }, + /* + * The rest of the test case just confirms supported hookpoints + * with the same test logic. + */ + { + NS_TEST_ID("async from setup"), + NS_QUERY_SETUP, + NS_QUERY_SETUP, + hook_async_query_setup, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from lookup"), + NS_QUERY_LOOKUP_BEGIN, + NS_QUERY_LOOKUP_BEGIN, + hook_async_query_lookup_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from resume"), + NS_QUERY_RESUME_BEGIN, + NS_QUERY_RESUME_BEGIN, + hook_async_query_resume_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from resume restored"), + NS_QUERY_RESUME_RESTORED, + NS_QUERY_RESUME_BEGIN, + hook_async_query_resume_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from gotanswer"), + NS_QUERY_GOT_ANSWER_BEGIN, + NS_QUERY_GOT_ANSWER_BEGIN, + hook_async_query_got_answer_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from respond any"), + NS_QUERY_RESPOND_ANY_BEGIN, + NS_QUERY_RESPOND_ANY_BEGIN, + hook_async_query_respond_any_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from add answer"), + NS_QUERY_ADDANSWER_BEGIN, + NS_QUERY_ADDANSWER_BEGIN, + hook_async_query_addanswer_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from notfound"), + NS_QUERY_NOTFOUND_BEGIN, + NS_QUERY_NOTFOUND_BEGIN, + hook_async_query_notfound_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from prep delegation"), + NS_QUERY_PREP_DELEGATION_BEGIN, + NS_QUERY_PREP_DELEGATION_BEGIN, + hook_async_query_prep_delegation_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from zone delegation"), + NS_QUERY_ZONE_DELEGATION_BEGIN, + NS_QUERY_ZONE_DELEGATION_BEGIN, + hook_async_query_zone_delegation_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from delegation"), + NS_QUERY_DELEGATION_BEGIN, + NS_QUERY_DELEGATION_BEGIN, + hook_async_query_delegation_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from async delegation"), + NS_QUERY_DELEGATION_RECURSE_BEGIN, + NS_QUERY_DELEGATION_RECURSE_BEGIN, + hook_async_query_delegation_recurse_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from nodata"), + NS_QUERY_NODATA_BEGIN, + NS_QUERY_NODATA_BEGIN, + hook_async_query_nodata_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from nxdomain"), + NS_QUERY_NXDOMAIN_BEGIN, + NS_QUERY_NXDOMAIN_BEGIN, + hook_async_query_nxdomain_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from ncache"), + NS_QUERY_NCACHE_BEGIN, + NS_QUERY_NCACHE_BEGIN, + hook_async_query_ncache_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from CNAME"), + NS_QUERY_CNAME_BEGIN, + NS_QUERY_CNAME_BEGIN, + hook_async_query_cname_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from DNAME"), + NS_QUERY_DNAME_BEGIN, + NS_QUERY_DNAME_BEGIN, + hook_async_query_dname_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from prep response"), + NS_QUERY_PREP_RESPONSE_BEGIN, + NS_QUERY_PREP_RESPONSE_BEGIN, + hook_async_query_response_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from respond"), + NS_QUERY_RESPOND_BEGIN, + NS_QUERY_RESPOND_BEGIN, + hook_async_query_respond_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from done begin"), + NS_QUERY_DONE_BEGIN, + NS_QUERY_DONE_BEGIN, + hook_async_query_done_begin, + ISC_R_SUCCESS, + true, + false, + }, + { + NS_TEST_ID("async from done send"), + NS_QUERY_DONE_SEND, + NS_QUERY_DONE_BEGIN, + hook_async_query_done_begin, + ISC_R_SUCCESS, + true, + false, + }, + }; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + run_hookasync_test(&tests[i]); + } +} + +/***** +***** tests for higher level ("e2e") behavior of ns_query_hookasync(). +***** It exercises overall behavior for some selected cases, while +***** ns__query_hookasync_test exercises implementation details for a +***** simple scenario and for all supported hook points. +*****/ + +/*% + * Structure containing parameters for ns__query_hookasync_e2e_test(). + */ +typedef struct { + const ns_test_id_t id; /* libns test identifier */ + const char *qname; /* QNAME */ + ns_hookpoint_t hookpoint; /* hook point specified for resume */ + isc_result_t start_result; /* result of 'runasync' */ + bool do_cancel; /* true if query should be canceled + * in test */ + dns_rcode_t expected_rcode; +} ns__query_hookasync_e2e_test_params_t; + +/* data structure passed from tests to hooks */ +typedef struct hookasync_e2e_data { + bool async; /* true if in a hook-triggered + * asynchronous process */ + ns_hook_resevent_t *rev; /* resume event sent on completion */ + ns_hookpoint_t hookpoint; /* specifies where to resume */ + isc_result_t start_result; /* result of 'runasync' */ + dns_rcode_t expected_rcode; + bool done; /* if SEND_DONE hook is called */ +} hookasync_e2e_data_t; + +/* Cancel callback. Just need to be defined, it doesn't have to do anything. */ +static void +cancel_e2ehookactx(ns_hookasync_t *ctx) { + UNUSED(ctx); +} + +/* 'runasync' callback passed to ns_query_hookasync */ +static isc_result_t +test_hookasync_e2e(query_ctx_t *qctx, isc_mem_t *memctx, void *arg, + isc_task_t *task, isc_taskaction_t action, void *evarg, + ns_hookasync_t **ctxp) { + ns_hookasync_t *ctx = NULL; + ns_hook_resevent_t *rev = NULL; + hookasync_e2e_data_t *asdata = arg; + + if (asdata->start_result != ISC_R_SUCCESS) { + return (asdata->start_result); + } + + ctx = isc_mem_get(memctx, sizeof(*ctx)); + rev = (ns_hook_resevent_t *)isc_event_allocate( + memctx, task, NS_EVENT_HOOKASYNCDONE, action, evarg, + sizeof(*rev)); + + rev->hookpoint = asdata->hookpoint; + rev->saved_qctx = qctx; + rev->ctx = ctx; + asdata->rev = rev; + + *ctx = (ns_hookasync_t){ .private = asdata }; + isc_mem_attach(memctx, &ctx->mctx); + ctx->destroy = destroy_hookactx; + ctx->cancel = cancel_e2ehookactx; + + *ctxp = ctx; + return (ISC_R_SUCCESS); +} + +static ns_hookresult_t +hook_async_e2e(void *arg, void *data, isc_result_t *resultp) { + query_ctx_t *qctx = arg; + hookasync_e2e_data_t *asdata = data; + isc_result_t result; + + if (!asdata->async) { + /* Initial call to the hook; start async event */ + result = ns_query_hookasync(qctx, test_hookasync_e2e, asdata); + if (result != ISC_R_SUCCESS) { + *resultp = result; + return (NS_HOOK_RETURN); + } + + asdata->async = true; + asdata->rev->origresult = *resultp; /* save it for resume */ + *resultp = ISC_R_UNSET; + return (NS_HOOK_RETURN); + } else { + /* Resume from the completion of async event */ + asdata->async = false; + /* Don't touch 'resultp' */ + return (NS_HOOK_CONTINUE); + } +} + +/* + * Check whether the final response has expected the RCODE according to + * the test scenario. + */ +static ns_hookresult_t +hook_donesend(void *arg, void *data, isc_result_t *resultp) { + query_ctx_t *qctx = arg; + hookasync_e2e_data_t *asdata = data; + + INSIST(qctx->client->message->rcode == asdata->expected_rcode); + asdata->done = true; /* Let the test know this hook is called */ + *resultp = ISC_R_UNSET; + return (NS_HOOK_CONTINUE); +} + +static void +run_hookasync_e2e_test(const ns__query_hookasync_e2e_test_params_t *test) { + query_ctx_t *qctx = NULL; + isc_result_t result; + hookasync_e2e_data_t asdata = { + .async = false, + .hookpoint = test->hookpoint, + .start_result = test->start_result, + .expected_rcode = test->expected_rcode, + .done = false, + }; + const ns_hook_t donesend_hook = { + .action = hook_donesend, + .action_data = &asdata, + }; + const ns_hook_t hook = { + .action = hook_async_e2e, + .action_data = &asdata, + }; + const ns_test_qctx_create_params_t qctx_params = { + .qname = test->qname, + .qtype = dns_rdatatype_a, + .with_cache = true, + }; + + ns__hook_table = NULL; + ns_hooktable_create(mctx, &ns__hook_table); + ns_hook_add(ns__hook_table, mctx, test->hookpoint, &hook); + ns_hook_add(ns__hook_table, mctx, NS_QUERY_DONE_SEND, &donesend_hook); + + result = ns_test_qctx_create(&qctx_params, &qctx); + INSIST(result == ISC_R_SUCCESS); + + isc_sockaddr_any(&qctx->client->peeraddr); /* for sortlist */ + qctx->client->sendcb = send_noop; + + /* Load a zone. it should have ns.foo/A */ + result = ns_test_serve_zone("foo", TESTS_DIR "/testdata/query/foo.db", + qctx->client->view); + INSIST(result == ISC_R_SUCCESS); + + /* + * We expect to have a response sent all cases, so we need to + * setup reqhandle (which will be detached on the send). + */ + isc_nmhandle_attach(qctx->client->handle, &qctx->client->reqhandle); + + /* Handle the query. hook-based async event will be triggered. */ + qctx->client->state = NS_CLIENTSTATE_WORKING; + ns__query_start(qctx); + + /* If specified cancel the query at this point. */ + if (test->do_cancel) { + ns_query_cancel(qctx->client); + } + + if (test->start_result == ISC_R_SUCCESS) { + /* + * If async event has started, manually invoke the done event. + */ + INSIST(asdata.async); + asdata.rev->ev_action(asdata.rev->ev_sender, + (isc_event_t *)asdata.rev); + + /* + * Usually 'async' is reset to false on the 2nd call to + * the hook. But the hook isn't called if the query is + * canceled. + */ + INSIST(asdata.done == !test->do_cancel); + INSIST(asdata.async == test->do_cancel); + } else { + INSIST(!asdata.async); + } + + /* Cleanup */ + ns_test_qctx_destroy(&qctx); + ns_test_cleanup_zone(); + ns_hooktable_free(mctx, (void **)&ns__hook_table); +} + +ISC_RUN_TEST_IMPL(ns_query_hookasync_e2e) { + UNUSED(state); + + const ns__query_hookasync_e2e_test_params_t tests[] = { + { + NS_TEST_ID("positive answer"), + "ns.foo", + NS_QUERY_GOT_ANSWER_BEGIN, + ISC_R_SUCCESS, + false, + dns_rcode_noerror, + }, + { + NS_TEST_ID("NXDOMAIN"), + "notexist.foo", + NS_QUERY_NXDOMAIN_BEGIN, + ISC_R_SUCCESS, + false, + dns_rcode_nxdomain, + }, + { + NS_TEST_ID("async fail"), + "ns.foo", + NS_QUERY_DONE_BEGIN, + ISC_R_FAILURE, + false, + -1, + }, + { + NS_TEST_ID("cancel query"), + "ns.foo", + NS_QUERY_DONE_BEGIN, + ISC_R_SUCCESS, + true, + -1, + }, + }; + + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + run_hookasync_e2e_test(&tests[i]); + } +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(ns_query_sfcache, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(ns_query_start, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(ns_query_hookasync, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(ns_query_hookasync_e2e, setup_test, teardown_test) + +ISC_TEST_LIST_END +ISC_TEST_MAIN diff --git a/tests/ns/testdata/notify/notify1.msg b/tests/ns/testdata/notify/notify1.msg new file mode 100644 index 0000000..a84193b --- /dev/null +++ b/tests/ns/testdata/notify/notify1.msg @@ -0,0 +1,3 @@ +# notify for example.com +10 a6 10 10 00 01 00 00 00 00 00 00 07 65 78 61 +6d 70 6c 65 03 63 6f 6d 00 00 06 00 01 diff --git a/tests/ns/testdata/notify/zone1.db b/tests/ns/testdata/notify/zone1.db new file mode 100644 index 0000000..b218d6d --- /dev/null +++ b/tests/ns/testdata/notify/zone1.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1000 +@ in soa localhost. postmaster.localhost. ( + 1993050801 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + in ns ns.example.com. + in ns ns2.example.com. + in ns ns3.example.com. +ns in a 10.0.0.1 +ns2 in a 10.0.0.2 +ns3 in a 10.0.0.3 + +a in a 1.2.3.4 diff --git a/tests/ns/testdata/query/foo.db b/tests/ns/testdata/query/foo.db new file mode 100644 index 0000000..5fb2c42 --- /dev/null +++ b/tests/ns/testdata/query/foo.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA localhost. postmaster.localhost. ( + 1 ;serial + 3600 ;refresh + 1800 ;retry + 604800 ;expiration + 3600 ) ;minimum + IN NS ns +ns IN A 127.0.0.1 diff --git a/tests/unit-test-driver.sh.in b/tests/unit-test-driver.sh.in new file mode 100644 index 0000000..9a60db1 --- /dev/null +++ b/tests/unit-test-driver.sh.in @@ -0,0 +1,60 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +TOP_BUILDDIR=@abs_top_builddir@ +TOP_SRCDIR=@abs_top_srcdir@ + +if [ -z "${1}" ]; then + echo "Usage: ${0} test_program" >&2 + exit 1 +fi + +TEST_PROGRAM="${1}" +TIMEOUT=300 + +"${TEST_PROGRAM}" & +TEST_PROGRAM_PID=${!} +STATUS=124 +while [ ${TIMEOUT} -gt 0 ]; do + if ! kill -0 "${TEST_PROGRAM_PID}" 2>/dev/null; then + wait "${TEST_PROGRAM_PID}" + STATUS=${?} + break + fi + sleep 1 + TIMEOUT=$((TIMEOUT - 1)) +done +if [ ${TIMEOUT} -eq 0 ]; then + echo "PID ${TEST_PROGRAM_PID} exceeded run time limit, sending SIGABRT" >&2 + kill -ABRT "${TEST_PROGRAM_PID}" 2>/dev/null +fi + +TEST_PROGRAM_NAME=$(basename "${TEST_PROGRAM}") +TEST_PROGRAM_WORK_DIR=$(dirname "${TEST_PROGRAM}") +find "${TEST_PROGRAM_WORK_DIR}" -name 'core*' -or -name '*.core' | while read -r CORE_DUMP; do + BINARY=$(gdb --batch --core="${CORE_DUMP}" 2>/dev/null | sed -n "s/^Core was generated by \`\(.*\)'\.\$/\1/p") + if ! echo "${BINARY}" | grep -q "${TEST_PROGRAM_NAME}\$"; then + continue + fi + echo "I:${TEST_PROGRAM_NAME}:Core dump found: ${CORE_DUMP}" + echo "D:${TEST_PROGRAM_NAME}:backtrace from ${CORE_DUMP} start" + "${TOP_BUILDDIR}/libtool" --mode=execute gdb \ + --batch \ + --command="${TOP_SRCDIR}/bin/tests/system/run.gdb" \ + --core="${CORE_DUMP}" \ + -- \ + "${BINARY}" + echo "D:${TEST_PROGRAM_NAME}:backtrace from ${CORE_DUMP} end" +done + +exit ${STATUS} |