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 /bin/delv | |
parent | Initial commit. (diff) | |
download | bind9-0cd617f6bad00b68e380aeb0024ef4dc1985191c.tar.xz bind9-0cd617f6bad00b68e380aeb0024ef4dc1985191c.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 'bin/delv')
-rw-r--r-- | bin/delv/Makefile.am | 21 | ||||
-rw-r--r-- | bin/delv/Makefile.in | 823 | ||||
-rw-r--r-- | bin/delv/delv.c | 1868 | ||||
-rw-r--r-- | bin/delv/delv.rst | 364 |
4 files changed, 3076 insertions, 0 deletions
diff --git a/bin/delv/Makefile.am b/bin/delv/Makefile.am new file mode 100644 index 0000000..5405023 --- /dev/null +++ b/bin/delv/Makefile.am @@ -0,0 +1,21 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + -I$(top_builddir)/include \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(LIBIRS_CFLAGS) + +AM_CPPFLAGS += \ + -DSYSCONFDIR=\"${sysconfdir}\" + +bin_PROGRAMS = delv + +delv_SOURCES = \ + delv.c +delv_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(LIBIRS_LIBS) diff --git a/bin/delv/Makefile.in b/bin/delv/Makefile.in new file mode 100644 index 0000000..b86bfb5 --- /dev/null +++ b/bin/delv/Makefile.in @@ -0,0 +1,823 @@ +# 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 + +bin_PROGRAMS = delv$(EXEEXT) +subdir = bin/delv +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 = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_delv_OBJECTS = delv.$(OBJEXT) +delv_OBJECTS = $(am_delv_OBJECTS) +delv_DEPENDENCIES = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) \ + $(LIBIRS_LIBS) +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)/delv.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 = $(delv_SOURCES) +DIST_SOURCES = $(delv_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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +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) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include -I$(top_builddir)/include $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) $(LIBISCCFG_CFLAGS) $(LIBIRS_CFLAGS) \ + -DSYSCONFDIR=\"${sysconfdir}\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +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 + +delv_SOURCES = \ + delv.c + +delv_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(LIBIRS_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(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 bin/delv/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/delv/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): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_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 + +delv$(EXEEXT): $(delv_OBJECTS) $(delv_DEPENDENCIES) $(EXTRA_delv_DEPENDENCIES) + @rm -f delv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(delv_OBJECTS) $(delv_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delv.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 +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 +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +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: + +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-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/delv.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-binPROGRAMS + +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)/delv.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: uninstall-binPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS 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-binPROGRAMS 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 tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-binPROGRAMS 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/bin/delv/delv.c b/bin/delv/delv.c new file mode 100644 index 0000000..e1e9e7f --- /dev/null +++ b/bin/delv/delv.c @@ -0,0 +1,1868 @@ +/* + * 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 <arpa/inet.h> +#include <bind.keys.h> +#include <inttypes.h> +#include <netdb.h> +#include <netinet/in.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include <isc/app.h> +#include <isc/attributes.h> +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/hex.h> +#include <isc/log.h> +#include <isc/managers.h> +#include <isc/md.h> +#include <isc/mem.h> +#include <isc/netmgr.h> +#include <isc/parseint.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/sockaddr.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/byaddr.h> +#include <dns/client.h> +#include <dns/fixedname.h> +#include <dns/keytable.h> +#include <dns/keyvalues.h> +#include <dns/log.h> +#include <dns/masterdump.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdataclass.h> +#include <dns/rdataset.h> +#include <dns/rdatastruct.h> +#include <dns/rdatatype.h> +#include <dns/secalg.h> +#include <dns/view.h> + +#include <dst/dst.h> + +#include <isccfg/log.h> +#include <isccfg/namedconf.h> + +#include <irs/resconf.h> + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +#define MAXNAME (DNS_NAME_MAXTEXT + 1) + +/* Variables used internally by delv. */ +char *progname; +static isc_mem_t *mctx = NULL; +static isc_log_t *lctx = NULL; + +/* Configurables */ +static char *server = NULL; +static const char *port = "53"; +static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL; +static isc_sockaddr_t a4, a6; +static char *curqname = NULL, *qname = NULL; +static bool classset = false; +static dns_rdatatype_t qtype = dns_rdatatype_none; +static bool typeset = false; + +static unsigned int styleflags = 0; +static uint32_t splitwidth = 0xffffffff; +static bool showcomments = true, showdnssec = true, showtrust = true, + rrcomments = true, noclass = false, nocrypto = false, nottl = false, + multiline = false, short_form = false, print_unknown_format = false, + yaml = false; + +static bool resolve_trace = false, validator_trace = false, + message_trace = false; + +static bool use_ipv4 = true, use_ipv6 = true; + +static bool cdflag = false, no_sigs = false, root_validation = true; + +static bool use_tcp = false; + +static char *anchorfile = NULL; +static char *trust_anchor = NULL; +static int num_keys = 0; + +static dns_fixedname_t afn; +static dns_name_t *anchor_name = NULL; + +/* Default bind.keys contents */ +static char anchortext[] = TRUST_ANCHORS; + +/* + * Static function prototypes + */ +static isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict); + +static isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc); + +static void +usage(void) { + fprintf(stderr, + "Usage: delv [@server] {q-opt} {d-opt} [domain] [q-type] " + "[q-class]\n" + "Where: domain is in the Domain Name System\n" + " q-class is one of (in,hs,ch,...) [default: in]\n" + " q-type is one of " + "(a,any,mx,ns,soa,hinfo,axfr,txt,...) " + "[default:a]\n" + " q-opt is one of:\n" + " -4 (use IPv4 query " + "transport " + "only)\n" + " -6 (use IPv6 query " + "transport " + "only)\n" + " -a anchor-file (specify root trust " + "anchor)\n" + " -b address[#port] (bind to source " + "address/port)\n" + " -c class (option included for " + "compatibility;\n" + " -d level (set debugging level)\n" + " -h (print help and exit)\n" + " -i (disable DNSSEC " + "validation)\n" + " -m (enable memory usage " + "debugging)\n" + " -p port (specify port number)\n" + " -q name (specify query name)\n" + " -t type (specify query type)\n" + " only IN is supported)\n" + " -v (print version and " + "exit)\n" + " -x dot-notation (shortcut for reverse " + "lookups)\n" + " d-opt is of the form +keyword[=value], where " + "keyword " + "is:\n" + " +[no]all (Set or clear all " + "display " + "flags)\n" + " +[no]class (Control display of " + "class)\n" + " +[no]comments (Control display of " + "comment lines)\n" + " +[no]crypto (Control display of " + "cryptographic\n" + " fields in records)\n" + " +[no]dlv (Obsolete)\n" + " +[no]dnssec (Display DNSSEC " + "records)\n" + " +[no]mtrace (Trace messages " + "received)\n" + " +[no]multiline (Print records in an " + "expanded format)\n" + " +[no]root (DNSSEC validation trust " + "anchor)\n" + " +[no]rrcomments (Control display of " + "per-record " + "comments)\n" + " +[no]rtrace (Trace resolver " + "fetches)\n" + " +[no]short (Short form answer)\n" + " +[no]split=## (Split hex/base64 fields " + "into chunks)\n" + " +[no]tcp (TCP mode)\n" + " +[no]ttl (Control display of ttls " + "in records)\n" + " +[no]trust (Control display of " + "trust " + "level)\n" + " +[no]unknownformat (Print RDATA in RFC 3597 " + "\"unknown\" format)\n" + " +[no]vtrace (Trace validation " + "process)\n" + " +[no]yaml (Present the results as " + "YAML)\n"); + exit(1); +} + +noreturn static void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +fatal(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + +static void +warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +warn(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: warning: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +} + +static isc_logcategory_t categories[] = { { "delv", 0 }, { NULL, 0 } }; +#define LOGCATEGORY_DEFAULT (&categories[0]) +#define LOGMODULE_DEFAULT (&modules[0]) + +static isc_logmodule_t modules[] = { { "delv", 0 }, { NULL, 0 } }; + +static void +delv_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); + +static void +delv_log(int level, const char *fmt, ...) { + va_list ap; + char msgbuf[2048]; + + if (!isc_log_wouldlog(lctx, level)) { + return; + } + + va_start(ap, fmt); + + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, level, "%s", + msgbuf); + va_end(ap); +} + +static int loglevel = 0; + +static void +setup_logging(FILE *errout) { + 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_registermodules(lctx, modules); + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + cfg_log_init(lctx); + + destination.file.stream = errout; + 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, + ISC_LOG_PRINTPREFIX); + + isc_log_setdebuglevel(lctx, loglevel); + isc_log_settag(logconfig, ";; "); + + result = isc_log_usechannel(logconfig, "stderr", + ISC_LOGCATEGORY_DEFAULT, NULL); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'stderr'"); + } + + if (resolve_trace && loglevel < 1) { + isc_log_createchannel(logconfig, "resolver", ISC_LOG_TOFILEDESC, + ISC_LOG_DEBUG(1), &destination, + ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "resolver", + DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'resolver'"); + } + } + + if (validator_trace && loglevel < 3) { + isc_log_createchannel(logconfig, "validator", + ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(3), + &destination, ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "validator", + DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_VALIDATOR); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'validator'"); + } + } + + if (message_trace && loglevel < 10) { + isc_log_createchannel(logconfig, "messages", ISC_LOG_TOFILEDESC, + ISC_LOG_DEBUG(10), &destination, + ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "messages", + DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_PACKETS); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'messagse'"); + } + } +} + +static void +print_status(dns_rdataset_t *rdataset) { + char buf[1024] = { 0 }; + + REQUIRE(rdataset != NULL); + + if (!showtrust || !dns_rdataset_isassociated(rdataset)) { + return; + } + + buf[0] = '\0'; + + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { + strlcat(buf, "negative response", sizeof(buf)); + strlcat(buf, (yaml ? "_" : ", "), sizeof(buf)); + } + + switch (rdataset->trust) { + case dns_trust_none: + strlcat(buf, "untrusted", sizeof(buf)); + break; + case dns_trust_pending_additional: + strlcat(buf, "signed additional data", sizeof(buf)); + if (!yaml) { + strlcat(buf, ", ", sizeof(buf)); + } + strlcat(buf, "pending validation", sizeof(buf)); + break; + case dns_trust_pending_answer: + strlcat(buf, "signed answer", sizeof(buf)); + if (!yaml) { + strlcat(buf, ", ", sizeof(buf)); + } + strlcat(buf, "pending validation", sizeof(buf)); + break; + case dns_trust_additional: + strlcat(buf, "unsigned additional data", sizeof(buf)); + break; + case dns_trust_glue: + strlcat(buf, "glue data", sizeof(buf)); + break; + case dns_trust_answer: + if (root_validation) { + strlcat(buf, "unsigned answer", sizeof(buf)); + } else { + strlcat(buf, "answer not validated", sizeof(buf)); + } + break; + case dns_trust_authauthority: + strlcat(buf, "authority data", sizeof(buf)); + break; + case dns_trust_authanswer: + strlcat(buf, "authoritative", sizeof(buf)); + break; + case dns_trust_secure: + strlcat(buf, "fully validated", sizeof(buf)); + break; + case dns_trust_ultimate: + strlcat(buf, "ultimate trust", sizeof(buf)); + break; + } + + if (yaml) { + char *p; + + /* Convert spaces to underscores for YAML */ + for (p = buf; p != NULL && *p != '\0'; p++) { + if (*p == ' ') { + *p = '_'; + } + } + + printf(" - %s:\n", buf); + } else { + printf("; %s\n", buf); + } +} + +static isc_result_t +printdata(dns_rdataset_t *rdataset, dns_name_t *owner, + dns_master_style_t *style) { + isc_result_t result = ISC_R_SUCCESS; + static dns_trust_t trust; + static bool first = true; + isc_buffer_t target; + isc_region_t r; + char *t = NULL; + int len = 2048; + + if (!dns_rdataset_isassociated(rdataset)) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(owner, namebuf, sizeof(namebuf)); + delv_log(ISC_LOG_DEBUG(4), "WARN: empty rdataset %s", namebuf); + return (ISC_R_SUCCESS); + } + + if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) { + return (ISC_R_SUCCESS); + } + + if (first || rdataset->trust != trust) { + if (!first && showtrust && !short_form && !yaml) { + putchar('\n'); + } + print_status(rdataset); + trust = rdataset->trust; + first = false; + } + + do { + t = isc_mem_get(mctx, len); + + isc_buffer_init(&target, t, len); + if (short_form) { + dns_rdata_t rdata = DNS_RDATA_INIT; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + if ((rdataset->attributes & + DNS_RDATASETATTR_NEGATIVE) != 0) + { + continue; + } + + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tofmttext( + &rdata, dns_rootname, styleflags, 0, + splitwidth, " ", &target); + if (result != ISC_R_SUCCESS) { + break; + } + + if (isc_buffer_availablelength(&target) < 1) { + result = ISC_R_NOSPACE; + break; + } + + isc_buffer_putstr(&target, "\n"); + + dns_rdata_reset(&rdata); + } + } else { + dns_indent_t indent = { " ", 2 }; + if (!yaml && (rdataset->attributes & + DNS_RDATASETATTR_NEGATIVE) != 0) + { + isc_buffer_putstr(&target, "; "); + } + result = dns_master_rdatasettotext( + owner, rdataset, style, yaml ? &indent : NULL, + &target); + } + + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, t, len); + len += 1024; + } else if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } else { + CHECK(result); + } + } while (result == ISC_R_NOSPACE); + + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + +cleanup: + if (t != NULL) { + isc_mem_put(mctx, t, len); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +setup_style(dns_master_style_t **stylep) { + isc_result_t result; + dns_master_style_t *style = NULL; + + REQUIRE(stylep != NULL && *stylep == NULL); + + styleflags |= DNS_STYLEFLAG_REL_OWNER; + if (yaml) { + styleflags |= DNS_STYLEFLAG_YAML; + } else { + if (showcomments) { + styleflags |= DNS_STYLEFLAG_COMMENT; + } + if (print_unknown_format) { + styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; + } + if (rrcomments) { + styleflags |= DNS_STYLEFLAG_RRCOMMENT; + } + if (nottl) { + styleflags |= DNS_STYLEFLAG_NO_TTL; + } + if (noclass) { + styleflags |= DNS_STYLEFLAG_NO_CLASS; + } + if (nocrypto) { + styleflags |= DNS_STYLEFLAG_NOCRYPTO; + } + if (multiline) { + styleflags |= DNS_STYLEFLAG_MULTILINE; + styleflags |= DNS_STYLEFLAG_COMMENT; + } + } + + if (multiline || (nottl && noclass)) { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 24, + 32, 80, 8, splitwidth, mctx); + } else if (nottl || noclass) { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 32, + 40, 80, 8, splitwidth, mctx); + } else { + result = dns_master_stylecreate(&style, styleflags, 24, 32, 40, + 48, 80, 8, splitwidth, mctx); + } + + if (result == ISC_R_SUCCESS) { + *stylep = style; + } + return (result); +} + +static isc_result_t +convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) { + isc_result_t result; + isc_buffer_t b; + dns_name_t *n; + unsigned int len; + + REQUIRE(fn != NULL && name != NULL && text != NULL); + len = strlen(text); + + isc_buffer_constinit(&b, text, len); + isc_buffer_add(&b, len); + n = dns_fixedname_initname(fn); + + result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", text, + isc_result_totext(result)); + return (result); + } + + *name = n; + return (ISC_R_SUCCESS); +} + +static isc_result_t +key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { + dns_rdata_dnskey_t dnskey; + dns_rdata_ds_t ds; + uint32_t rdata1, rdata2, rdata3; + const char *datastr = NULL, *keynamestr = NULL, *atstr = NULL; + unsigned char data[4096]; + isc_buffer_t databuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + dns_fixedname_t fkeyname; + dns_name_t *keyname; + isc_result_t result; + bool match_root = false; + enum { + INITIAL_KEY, + STATIC_KEY, + INITIAL_DS, + STATIC_DS, + TRUSTED + } anchortype; + const cfg_obj_t *obj; + + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + CHECK(convert_name(&fkeyname, &keyname, keynamestr)); + + if (!root_validation) { + return (ISC_R_SUCCESS); + } + + if (anchor_name) { + match_root = dns_name_equal(keyname, anchor_name); + } + + if (!match_root) { + return (ISC_R_SUCCESS); + } + + if (!root_validation) { + return (ISC_R_SUCCESS); + } + + delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor); + + /* if DNSKEY, flags; if DS, key tag */ + rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); + + /* if DNSKEY, protocol; if DS, algorithm */ + rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); + + /* if DNSKEY, algorithm; if DS, digest type */ + rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); + + /* What type of trust anchor is this? */ + obj = cfg_tuple_get(key, "anchortype"); + if (cfg_obj_isvoid(obj)) { + /* + * "anchortype" is not defined, this must be a static-key + * configured with trusted-keys. + */ + anchortype = STATIC_KEY; + } else { + atstr = cfg_obj_asstring(obj); + if (strcasecmp(atstr, "static-key") == 0) { + anchortype = STATIC_KEY; + } else if (strcasecmp(atstr, "static-ds") == 0) { + anchortype = STATIC_DS; + } else if (strcasecmp(atstr, "initial-key") == 0) { + anchortype = INITIAL_KEY; + } else if (strcasecmp(atstr, "initial-ds") == 0) { + anchortype = INITIAL_DS; + } else { + delv_log(ISC_LOG_ERROR, + "key '%s': invalid initialization method '%s'", + keynamestr, atstr); + result = ISC_R_FAILURE; + goto cleanup; + } + } + + isc_buffer_init(&databuf, data, sizeof(data)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + if (rdata1 > 0xffff) { + CHECK(ISC_R_RANGE); + } + if (rdata2 > 0xff) { + CHECK(ISC_R_RANGE); + } + if (rdata3 > 0xff) { + CHECK(ISC_R_RANGE); + } + + switch (anchortype) { + case STATIC_KEY: + case INITIAL_KEY: + case TRUSTED: + dnskey.common.rdclass = dns_rdataclass_in; + dnskey.common.rdtype = dns_rdatatype_dnskey; + dnskey.mctx = NULL; + + ISC_LINK_INIT(&dnskey.common, link); + + dnskey.flags = (uint16_t)rdata1; + dnskey.protocol = (uint8_t)rdata2; + dnskey.algorithm = (uint8_t)rdata3; + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_base64_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + dnskey.datalen = r.length; + dnskey.data = r.base; + + CHECK(dns_rdata_fromstruct(NULL, dnskey.common.rdclass, + dnskey.common.rdtype, &dnskey, + &rrdatabuf)); + CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, + dns_rdatatype_dnskey, keyname, + &rrdatabuf)); + break; + case INITIAL_DS: + case STATIC_DS: + ds.common.rdclass = dns_rdataclass_in; + ds.common.rdtype = dns_rdatatype_ds; + ds.mctx = NULL; + + ISC_LINK_INIT(&ds.common, link); + + ds.key_tag = (uint16_t)rdata1; + ds.algorithm = (uint8_t)rdata2; + ds.digest_type = (uint8_t)rdata3; + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_hex_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + + switch (ds.digest_type) { + case DNS_DSDIGEST_SHA1: + if (r.length != ISC_SHA1_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA256: + if (r.length != ISC_SHA256_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA384: + if (r.length != ISC_SHA384_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + } + + ds.length = r.length; + ds.digest = r.base; + + CHECK(dns_rdata_fromstruct(NULL, ds.common.rdclass, + ds.common.rdtype, &ds, &rrdatabuf)); + CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, + dns_rdatatype_ds, keyname, + &rrdatabuf)); + } + + num_keys++; + +cleanup: + if (result == DST_R_NOCRYPTO) { + cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); + } else if (result == DST_R_UNSUPPORTEDALG) { + cfg_obj_log(key, lctx, ISC_LOG_WARNING, + "skipping trusted key '%s': %s", keynamestr, + isc_result_totext(result)); + result = ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + cfg_obj_log(key, lctx, ISC_LOG_ERROR, + "failed to add trusted key '%s': %s", keynamestr, + isc_result_totext(result)); + result = ISC_R_FAILURE; + } + + return (result); +} + +static isc_result_t +load_keys(const cfg_obj_t *keys, dns_client_t *client) { + const cfg_listelt_t *elt, *elt2; + const cfg_obj_t *key, *keylist; + isc_result_t result = ISC_R_SUCCESS; + + for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) + { + keylist = cfg_listelt_value(elt); + + for (elt2 = cfg_list_first(keylist); elt2 != NULL; + elt2 = cfg_list_next(elt2)) + { + key = cfg_listelt_value(elt2); + CHECK(key_fromconfig(key, client)); + } + } + +cleanup: + if (result == DST_R_NOCRYPTO) { + result = ISC_R_SUCCESS; + } + return (result); +} + +static isc_result_t +setup_dnsseckeys(dns_client_t *client) { + isc_result_t result; + cfg_parser_t *parser = NULL; + const cfg_obj_t *trusted_keys = NULL; + const cfg_obj_t *managed_keys = NULL; + const cfg_obj_t *trust_anchors = NULL; + cfg_obj_t *bindkeys = NULL; + const char *filename = anchorfile; + + if (!root_validation) { + return (ISC_R_SUCCESS); + } + + if (filename == NULL) { + filename = SYSCONFDIR "/bind.keys"; + } + + if (trust_anchor == NULL) { + trust_anchor = isc_mem_strdup(mctx, "."); + } + + if (trust_anchor != NULL) { + CHECK(convert_name(&afn, &anchor_name, trust_anchor)); + } + + CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); + + if (access(filename, R_OK) != 0) { + if (anchorfile != NULL) { + fatal("Unable to read key file '%s'", anchorfile); + } + } else { + result = cfg_parse_file(parser, filename, &cfg_type_bindkeys, + &bindkeys); + if (result != ISC_R_SUCCESS) { + if (anchorfile != NULL) { + fatal("Unable to load keys from '%s'", + anchorfile); + } + } + } + + if (bindkeys == NULL) { + isc_buffer_t b; + + isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); + isc_buffer_add(&b, sizeof(anchortext) - 1); + cfg_parser_reset(parser); + result = cfg_parse_buffer(parser, &b, NULL, 0, + &cfg_type_bindkeys, 0, &bindkeys); + if (result != ISC_R_SUCCESS) { + fatal("Unable to parse built-in keys"); + } + } + + INSIST(bindkeys != NULL); + cfg_map_get(bindkeys, "trusted-keys", &trusted_keys); + cfg_map_get(bindkeys, "managed-keys", &managed_keys); + cfg_map_get(bindkeys, "trust-anchors", &trust_anchors); + + if (trusted_keys != NULL) { + CHECK(load_keys(trusted_keys, client)); + } + if (managed_keys != NULL) { + CHECK(load_keys(managed_keys, client)); + } + if (trust_anchors != NULL) { + CHECK(load_keys(trust_anchors, client)); + } + result = ISC_R_SUCCESS; + + if (num_keys == 0) { + fatal("No trusted keys were loaded"); + } + +cleanup: + if (bindkeys != NULL) { + cfg_obj_destroy(parser, &bindkeys); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", + isc_result_totext(result)); + } + return (result); +} + +static isc_result_t +addserver(dns_client_t *client) { + struct addrinfo hints, *res, *cur; + int gaierror; + struct in_addr in4; + struct in6_addr in6; + isc_sockaddr_t *sa; + isc_sockaddrlist_t servers; + uint32_t destport; + isc_result_t result; + dns_name_t *name = NULL; + + result = parse_uint(&destport, port, 0xffff, "port"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + + ISC_LIST_INIT(servers); + + if (inet_pton(AF_INET, server, &in4) == 1) { + if (!use_ipv4) { + fatal("Use of IPv4 disabled by -6"); + } + sa = isc_mem_get(mctx, sizeof(*sa)); + ISC_LINK_INIT(sa, link); + isc_sockaddr_fromin(sa, &in4, destport); + ISC_LIST_APPEND(servers, sa, link); + } else if (inet_pton(AF_INET6, server, &in6) == 1) { + if (!use_ipv6) { + fatal("Use of IPv6 disabled by -4"); + } + sa = isc_mem_get(mctx, sizeof(*sa)); + ISC_LINK_INIT(sa, link); + isc_sockaddr_fromin6(sa, &in6, destport); + ISC_LIST_APPEND(servers, sa, link); + } else { + memset(&hints, 0, sizeof(hints)); + if (!use_ipv6) { + hints.ai_family = AF_INET; + } else if (!use_ipv4) { + hints.ai_family = AF_INET6; + } else { + hints.ai_family = AF_UNSPEC; + } + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + gaierror = getaddrinfo(server, port, &hints, &res); + if (gaierror != 0) { + delv_log(ISC_LOG_ERROR, "getaddrinfo failed: %s", + gai_strerror(gaierror)); + return (ISC_R_FAILURE); + } + + result = ISC_R_SUCCESS; + for (cur = res; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET && + cur->ai_family != AF_INET6) + { + continue; + } + sa = isc_mem_get(mctx, sizeof(*sa)); + memset(sa, 0, sizeof(*sa)); + ISC_LINK_INIT(sa, link); + memmove(&sa->type, cur->ai_addr, cur->ai_addrlen); + sa->length = (unsigned int)cur->ai_addrlen; + ISC_LIST_APPEND(servers, sa, link); + } + freeaddrinfo(res); + CHECK(result); + } + + CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); + +cleanup: + while (!ISC_LIST_EMPTY(servers)) { + sa = ISC_LIST_HEAD(servers); + ISC_LIST_UNLINK(servers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "addserver: %s", + isc_result_totext(result)); + } + + return (result); +} + +static isc_result_t +findserver(dns_client_t *client) { + isc_result_t result; + irs_resconf_t *resconf = NULL; + isc_sockaddrlist_t *nameservers; + isc_sockaddr_t *sa, *next; + uint32_t destport; + + result = parse_uint(&destport, port, 0xffff, "port"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + + result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); + if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { + delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", + isc_result_totext(result)); + goto cleanup; + } + + /* Get nameservers from resolv.conf */ + nameservers = irs_resconf_getnameservers(resconf); + for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { + next = ISC_LIST_NEXT(sa, link); + + /* Set destination port */ + if (sa->type.sa.sa_family == AF_INET && use_ipv4) { + sa->type.sin.sin_port = htons(destport); + continue; + } + if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { + sa->type.sin6.sin6_port = htons(destport); + continue; + } + + /* Incompatible protocol family */ + ISC_LIST_UNLINK(*nameservers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + /* None found, use localhost */ + if (ISC_LIST_EMPTY(*nameservers)) { + if (use_ipv4) { + struct in_addr localhost; + localhost.s_addr = htonl(INADDR_LOOPBACK); + sa = isc_mem_get(mctx, sizeof(*sa)); + isc_sockaddr_fromin(sa, &localhost, destport); + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(*nameservers, sa, link); + } + + if (use_ipv6) { + sa = isc_mem_get(mctx, sizeof(*sa)); + isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(*nameservers, sa, link); + } + } + + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + nameservers); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", + isc_result_totext(result)); + } + +cleanup: + if (resconf != NULL) { + irs_resconf_destroy(&resconf); + } + return (result); +} + +static isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { + uint32_t n; + isc_result_t result = isc_parse_uint32(&n, value, 10); + if (result == ISC_R_SUCCESS && n > max) { + result = ISC_R_RANGE; + } + if (result != ISC_R_SUCCESS) { + printf("invalid %s '%s': %s\n", desc, value, + isc_result_totext(result)); + return (result); + } + *uip = n; + return (ISC_R_SUCCESS); +} + +static void +plus_option(char *option) { + isc_result_t result; + char *cmd, *value, *last = NULL; + bool state = true; + + INSIST(option != NULL); + + cmd = strtok_r(option, "=", &last); + if (cmd == NULL) { + printf(";; Invalid option %s\n", option); + return; + } + if (strncasecmp(cmd, "no", 2) == 0) { + cmd += 2; + state = false; + } + + value = strtok_r(NULL, "\0", &last); + +#define FULLCHECK(A) \ + do { \ + size_t _l = strlen(cmd); \ + if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ + goto invalid_option; \ + } while (0) + + switch (cmd[0]) { + case 'a': /* all */ + FULLCHECK("all"); + showcomments = state; + rrcomments = state; + showtrust = state; + break; + case 'c': + switch (cmd[1]) { + case 'd': /* cdflag */ + FULLCHECK("cdflag"); + cdflag = state; + break; + case 'l': /* class */ + FULLCHECK("class"); + noclass = !state; + break; + case 'o': /* comments */ + FULLCHECK("comments"); + showcomments = state; + break; + case 'r': /* crypto */ + FULLCHECK("crypto"); + nocrypto = !state; + break; + default: + goto invalid_option; + } + break; + case 'd': + switch (cmd[1]) { + case 'l': /* dlv */ + FULLCHECK("dlv"); + if (state) { + fprintf(stderr, "Invalid option: " + "+dlv is obsolete\n"); + exit(1); + } + break; + case 'n': /* dnssec */ + FULLCHECK("dnssec"); + showdnssec = state; + break; + default: + goto invalid_option; + } + break; + case 'm': + switch (cmd[1]) { + case 't': /* mtrace */ + message_trace = state; + if (state) { + resolve_trace = state; + } + break; + case 'u': /* multiline */ + FULLCHECK("multiline"); + multiline = state; + break; + default: + goto invalid_option; + } + break; + case 'r': + switch (cmd[1]) { + case 'o': /* root */ + FULLCHECK("root"); + if (state && no_sigs) { + break; + } + root_validation = state; + if (value != NULL) { + trust_anchor = isc_mem_strdup(mctx, value); + } + break; + case 'r': /* rrcomments */ + FULLCHECK("rrcomments"); + rrcomments = state; + break; + case 't': /* rtrace */ + FULLCHECK("rtrace"); + resolve_trace = state; + break; + default: + goto invalid_option; + } + break; + case 's': + switch (cmd[1]) { + case 'h': /* short */ + FULLCHECK("short"); + short_form = state; + if (short_form) { + multiline = false; + showcomments = false; + showtrust = false; + showdnssec = false; + } + break; + case 'p': /* split */ + FULLCHECK("split"); + if (value != NULL && !state) { + goto invalid_option; + } + if (!state) { + splitwidth = 0; + break; + } else if (value == NULL) { + break; + } + + result = parse_uint(&splitwidth, value, 1023, "split"); + if (splitwidth % 4 != 0) { + splitwidth = ((splitwidth + 3) / 4) * 4; + warn("split must be a multiple of 4; " + "adjusting to %d", + splitwidth); + } + /* + * There is an adjustment done in the + * totext_<rrtype>() functions which causes + * splitwidth to shrink. This is okay when we're + * using the default width but incorrect in this + * case, so we correct for it + */ + if (splitwidth) { + splitwidth += 3; + } + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse split"); + } + break; + default: + goto invalid_option; + } + break; + case 'u': + FULLCHECK("unknownformat"); + print_unknown_format = state; + break; + case 't': + switch (cmd[1]) { + case 'c': /* tcp */ + FULLCHECK("tcp"); + use_tcp = state; + break; + case 'r': /* trust */ + FULLCHECK("trust"); + showtrust = state; + break; + case 't': /* ttl */ + FULLCHECK("ttl"); + nottl = !state; + break; + default: + goto invalid_option; + } + break; + case 'v': /* vtrace */ + FULLCHECK("vtrace"); + validator_trace = state; + if (state) { + resolve_trace = state; + } + break; + case 'y': /* yaml */ + FULLCHECK("yaml"); + yaml = state; + if (state) { + rrcomments = false; + } + break; + default: + invalid_option: + /* + * We can also add a "need_value:" case here if we ever + * add a plus-option that requires a specified value + */ + fprintf(stderr, "Invalid option: +%s\n", option); + usage(); + } + return; +} + +/* + * options: "46a:b:c:d:himp:q:t:vx:"; + */ +static const char *single_dash_opts = "46himv"; +static const char *dash_opts = "46abcdhimpqtvx"; + +static bool +dash_option(char *option, char *next, bool *open_type_class) { + char opt, *value; + isc_result_t result; + bool value_from_next; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + char textname[MAXNAME]; + struct in_addr in4; + struct in6_addr in6; + in_port_t srcport; + uint32_t num; + char *hash; + + while (strpbrk(option, single_dash_opts) == &option[0]) { + /* + * Since the -[46himv] options do not take an argument, + * account for them (in any number and/or combination) + * if they appear as the first character(s) of a q-opt. + */ + opt = option[0]; + switch (opt) { + case '4': + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + fatal("IPv4 networking not available"); + } + if (use_ipv6) { + isc_net_disableipv6(); + use_ipv6 = false; + } + break; + case '6': + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + fatal("IPv6 networking not available"); + } + if (use_ipv4) { + isc_net_disableipv4(); + use_ipv4 = false; + } + break; + case 'h': + usage(); + exit(0); + case 'i': + no_sigs = true; + root_validation = false; + break; + case 'm': + /* handled in preparse_args() */ + break; + case 'v': + fprintf(stderr, "delv %s\n", PACKAGE_VERSION); + exit(0); + default: + UNREACHABLE(); + } + if (strlen(option) > 1U) { + option = &option[1]; + } else { + return (false); + } + } + opt = option[0]; + if (strlen(option) > 1U) { + value_from_next = false; + value = &option[1]; + } else { + value_from_next = true; + value = next; + } + if (value == NULL) { + goto invalid_option; + } + switch (opt) { + case 'a': + anchorfile = isc_mem_strdup(mctx, value); + return (value_from_next); + case 'b': + hash = strchr(value, '#'); + if (hash != NULL) { + result = parse_uint(&num, hash + 1, 0xffff, "port"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + srcport = num; + *hash = '\0'; + } else { + srcport = 0; + } + + if (inet_pton(AF_INET, value, &in4) == 1) { + if (srcaddr4 != NULL) { + fatal("Only one local address per family " + "can be specified\n"); + } + isc_sockaddr_fromin(&a4, &in4, srcport); + srcaddr4 = &a4; + } else if (inet_pton(AF_INET6, value, &in6) == 1) { + if (srcaddr6 != NULL) { + fatal("Only one local address per family " + "can be specified\n"); + } + isc_sockaddr_fromin6(&a6, &in6, srcport); + srcaddr6 = &a6; + } else { + if (hash != NULL) { + *hash = '#'; + } + fatal("Invalid address %s", value); + } + if (hash != NULL) { + *hash = '#'; + } + return (value_from_next); + case 'c': + if (classset) { + warn("extra query class"); + } + + *open_type_class = false; + tr.base = value; + tr.length = strlen(value); + result = dns_rdataclass_fromtext(&rdclass, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + classset = true; + } else if (rdclass != dns_rdataclass_in) { + warn("ignoring non-IN query class"); + } else { + warn("ignoring invalid class"); + } + return (value_from_next); + case 'd': + result = parse_uint(&num, value, 99, "debug level"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse debug level"); + } + loglevel = num; + return (value_from_next); + case 'p': + port = value; + return (value_from_next); + case 'q': + if (curqname != NULL) { + warn("extra query name"); + isc_mem_free(mctx, curqname); + } + curqname = isc_mem_strdup(mctx, value); + return (value_from_next); + case 't': + *open_type_class = false; + tr.base = value; + tr.length = strlen(value); + result = dns_rdatatype_fromtext(&rdtype, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (typeset) { + warn("extra query type"); + } + if (rdtype == dns_rdatatype_ixfr || + rdtype == dns_rdatatype_axfr) + { + fatal("Transfer not supported"); + } + qtype = rdtype; + typeset = true; + } else { + warn("ignoring invalid type"); + } + return (value_from_next); + case 'x': + result = get_reverse(textname, sizeof(textname), value, false); + if (result == ISC_R_SUCCESS) { + if (curqname != NULL) { + isc_mem_free(mctx, curqname); + warn("extra query name"); + } + curqname = isc_mem_strdup(mctx, textname); + if (typeset) { + warn("extra query type"); + } + qtype = dns_rdatatype_ptr; + typeset = true; + } else { + fprintf(stderr, "Invalid IP address %s\n", value); + exit(1); + } + return (value_from_next); + invalid_option: + default: + fprintf(stderr, "Invalid option: -%s\n", option); + usage(); + } + UNREACHABLE(); + return (false); +} + +/* + * Check for -m first to determine whether to enable + * memory debugging when setting up the memory context. + */ +static void +preparse_args(int argc, char **argv) { + bool ipv4only = false, ipv6only = false; + char *option; + + for (argc--, argv++; argc > 0; argc--, argv++) { + if (argv[0][0] != '-') { + continue; + } + + option = &argv[0][1]; + while (strpbrk(option, single_dash_opts) == &option[0]) { + switch (option[0]) { + case 'm': + isc_mem_debugging = ISC_MEM_DEBUGTRACE | + ISC_MEM_DEBUGRECORD; + break; + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + } + option = &option[1]; + } + + if (strlen(option) == 0U) { + continue; + } + + /* Look for dash value option. */ + if (strpbrk(option, dash_opts) != &option[0] || + strlen(option) > 1U) + { + /* Error or value in option. */ + continue; + } + + /* Dash value is next argument so we need to skip it. */ + argc--; + argv++; + + /* Handle missing argument */ + if (argc == 0) { + break; + } + } +} + +/* + * Argument parsing is based on dig, but simplified: only one + * QNAME/QCLASS/QTYPE tuple can be specified, and options have + * been removed that aren't applicable to delv. The interface + * should be familiar to dig users, however. + */ +static void +parse_args(int argc, char **argv) { + isc_result_t result; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + bool open_type_class = true; + + for (; argc > 0; argc--, argv++) { + if (argv[0][0] == '@') { + server = &argv[0][1]; + } else if (argv[0][0] == '+') { + plus_option(&argv[0][1]); + } else if (argv[0][0] == '-') { + if (argc <= 1) { + if (dash_option(&argv[0][1], NULL, + &open_type_class)) + { + argc--; + argv++; + } + } else { + if (dash_option(&argv[0][1], argv[1], + &open_type_class)) + { + argc--; + argv++; + } + } + } else { + /* + * Anything which isn't an option + */ + if (open_type_class) { + tr.base = argv[0]; + tr.length = strlen(argv[0]); + result = dns_rdatatype_fromtext( + &rdtype, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (typeset) { + warn("extra query type"); + } + if (rdtype == dns_rdatatype_ixfr || + rdtype == dns_rdatatype_axfr) + { + fatal("Transfer not supported"); + } + qtype = rdtype; + typeset = true; + continue; + } + result = dns_rdataclass_fromtext( + &rdclass, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (classset) { + warn("extra query class"); + } else if (rdclass != dns_rdataclass_in) + { + warn("ignoring non-IN " + "query class"); + } + continue; + } + } + + if (curqname == NULL) { + curqname = isc_mem_strdup(mctx, argv[0]); + } + } + } + + /* + * If no qname or qtype specified, search for root/NS + * If no qtype specified, use A + */ + if (!typeset) { + qtype = dns_rdatatype_a; + } + + if (curqname == NULL) { + qname = isc_mem_strdup(mctx, "."); + + if (!typeset) { + qtype = dns_rdatatype_ns; + } + } else { + qname = curqname; + } +} + +static isc_result_t +append_str(const char *text, int len, char **p, char *end) { + if (len > end - *p) { + return (ISC_R_NOSPACE); + } + memmove(*p, text, len); + *p += len; + return (ISC_R_SUCCESS); +} + +static isc_result_t +reverse_octets(const char *in, char **p, char *end) { + char *dot = strchr(in, '.'); + int len; + if (dot != NULL) { + isc_result_t result; + result = reverse_octets(dot + 1, p, end); + if (result != ISC_R_SUCCESS) { + return (result); + } + result = append_str(".", 1, p, end); + if (result != ISC_R_SUCCESS) { + return (result); + } + len = (int)(dot - in); + } else { + len = strlen(in); + } + return (append_str(in, len, p, end)); +} + +static isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict) { + int r; + isc_result_t result; + isc_netaddr_t addr; + + addr.family = AF_INET6; + r = inet_pton(AF_INET6, value, &addr.type.in6); + if (r > 0) { + /* This is a valid IPv6 address. */ + dns_fixedname_t fname; + dns_name_t *name; + unsigned int options = 0; + + name = dns_fixedname_initname(&fname); + result = dns_byaddr_createptrname(&addr, options, name); + if (result != ISC_R_SUCCESS) { + return (result); + } + dns_name_format(name, reverse, (unsigned int)len); + return (ISC_R_SUCCESS); + } else { + /* + * Not a valid IPv6 address. Assume IPv4. + * If 'strict' is not set, construct the + * in-addr.arpa name by blindly reversing + * octets whether or not they look like integers, + * so that this can be used for RFC2317 names + * and such. + */ + char *p = reverse; + char *end = reverse + len; + if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) { + return (DNS_R_BADDOTTEDQUAD); + } + result = reverse_octets(value, &p, end); + if (result != ISC_R_SUCCESS) { + return (result); + } + result = append_str(".in-addr.arpa.", 15, &p, end); + if (result != ISC_R_SUCCESS) { + return (result); + } + return (ISC_R_SUCCESS); + } +} + +int +main(int argc, char *argv[]) { + dns_client_t *client = NULL; + isc_result_t result; + dns_fixedname_t qfn; + dns_name_t *query_name, *response_name; + char namestr[DNS_NAME_FORMATSIZE]; + dns_rdataset_t *rdataset; + dns_namelist_t namelist; + unsigned int resopt; + isc_appctx_t *actx = NULL; + isc_nm_t *netmgr = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_timermgr_t *timermgr = NULL; + dns_master_style_t *style = NULL; + struct sigaction sa; + + progname = argv[0]; + preparse_args(argc, argv); + + argc--; + argv++; + + isc_mem_create(&mctx); + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + fatal("dst_lib_init failed: %d", result); + } + + CHECK(isc_appctx_create(mctx, &actx)); + + isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, &timermgr); + + parse_args(argc, argv); + + CHECK(setup_style(&style)); + + setup_logging(stderr); + + CHECK(isc_app_ctxstart(actx)); + + /* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) { + fatal("Couldn't set up signal handler"); + } + + /* Create client */ + result = dns_client_create(mctx, actx, taskmgr, netmgr, timermgr, 0, + &client, srcaddr4, srcaddr6); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "dns_client_create: %s", + isc_result_totext(result)); + goto cleanup; + } + + /* Set the nameserver */ + if (server != NULL) { + addserver(client); + } else { + findserver(client); + } + + CHECK(setup_dnsseckeys(client)); + + /* Construct QNAME */ + CHECK(convert_name(&qfn, &query_name, qname)); + + /* Set up resolution options */ + resopt = DNS_CLIENTRESOPT_NOCDFLAG; + if (no_sigs) { + resopt |= DNS_CLIENTRESOPT_NODNSSEC; + } + if (!root_validation) { + resopt |= DNS_CLIENTRESOPT_NOVALIDATE; + } + if (cdflag) { + resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG; + } + if (use_tcp) { + resopt |= DNS_CLIENTRESOPT_TCP; + } + + /* Perform resolution */ + ISC_LIST_INIT(namelist); + result = dns_client_resolve(client, query_name, dns_rdataclass_in, + qtype, resopt, &namelist); + if (result != ISC_R_SUCCESS && !yaml) { + delv_log(ISC_LOG_ERROR, "resolution failed: %s", + isc_result_totext(result)); + } + + if (yaml) { + printf("type: DELV_RESULT\n"); + dns_name_format(query_name, namestr, sizeof(namestr)); + printf("query_name: %s\n", namestr); + printf("status: %s\n", isc_result_totext(result)); + printf("records:\n"); + } + + for (response_name = ISC_LIST_HEAD(namelist); response_name != NULL; + response_name = ISC_LIST_NEXT(response_name, link)) + { + for (rdataset = ISC_LIST_HEAD(response_name->list); + rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) + { + result = printdata(rdataset, response_name, style); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "print data failed"); + } + } + } + + dns_client_freeresanswer(client, &namelist); + +cleanup: + if (trust_anchor != NULL) { + isc_mem_free(mctx, trust_anchor); + } + if (anchorfile != NULL) { + isc_mem_free(mctx, anchorfile); + } + if (qname != NULL) { + isc_mem_free(mctx, qname); + } + if (style != NULL) { + dns_master_styledestroy(&style, mctx); + } + if (client != NULL) { + dns_client_detach(&client); + } + + isc_managers_destroy(&netmgr, &taskmgr, &timermgr); + + if (actx != NULL) { + isc_appctx_destroy(&actx); + } + if (lctx != NULL) { + isc_log_destroy(&lctx); + } + isc_mem_detach(&mctx); + + dst_lib_destroy(); + + return (0); +} diff --git a/bin/delv/delv.rst b/bin/delv/delv.rst new file mode 100644 index 0000000..bf6cce1 --- /dev/null +++ b/bin/delv/delv.rst @@ -0,0 +1,364 @@ +.. 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. + +.. highlight: console + +.. iscman:: delv +.. program:: delv +.. _man_delv: + +delv - DNS lookup and validation utility +---------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`delv` [@server] [ [**-4**] | [**-6**] ] [**-a** anchor-file] [**-b** address] [**-c** class] [**-d** level] [**-i**] [**-m**] [**-p** port#] [**-q** name] [**-t** type] [**-x** addr] [name] [type] [class] [queryopt...] + +:program:`delv` [**-h**] + +:program:`delv` [**-v**] + +:program:`delv` [queryopt...] [query...] + +Description +~~~~~~~~~~~ + +:program:`delv` is a tool for sending DNS queries and validating the results, +using the same internal resolver and validator logic as :iscman:`named`. + +:program:`delv` sends to a specified name server all queries needed to +fetch and validate the requested data; this includes the original +requested query, subsequent queries to follow CNAME or DNAME chains, +queries for DNSKEY, and DS records to establish a chain of trust for +DNSSEC validation. It does not perform iterative resolution, but +simulates the behavior of a name server configured for DNSSEC validating +and forwarding. + +By default, responses are validated using the built-in DNSSEC trust anchor +for the root zone ("."). Records returned by :program:`delv` are either fully +validated or were not signed. If validation fails, an explanation of the +failure is included in the output; the validation process can be traced +in detail. Because :program:`delv` does not rely on an external server to carry +out validation, it can be used to check the validity of DNS responses in +environments where local name servers may not be trustworthy. + +Unless it is told to query a specific name server, :program:`delv` tries +each of the servers listed in ``/etc/resolv.conf``. If no usable server +addresses are found, :program:`delv` sends queries to the localhost +addresses (127.0.0.1 for IPv4, ::1 for IPv6). + +When no command-line arguments or options are given, :program:`delv` +performs an NS query for "." (the root zone). + +Simple Usage +~~~~~~~~~~~~ + +A typical invocation of :program:`delv` looks like: + +:: + + delv @server name type + +where: + +.. option:: server + + is the name or IP address of the name server to query. This can be an + IPv4 address in dotted-decimal notation or an IPv6 address in + colon-delimited notation. When the supplied ``server`` argument is a + hostname, :program:`delv` resolves that name before querying that name + server (note, however, that this initial lookup is *not* validated by + DNSSEC). + + If no ``server`` argument is provided, :program:`delv` consults + ``/etc/resolv.conf``; if an address is found there, it queries the + name server at that address. If either of the :option:`-4` or :option:`-6` + options is in use, then only addresses for the corresponding + transport are tried. If no usable addresses are found, :program:`delv` + sends queries to the localhost addresses (127.0.0.1 for IPv4, ::1 + for IPv6). + +.. option:: name + + is the domain name to be looked up. + +.. option:: type + + indicates what type of query is required - ANY, A, MX, etc. + ``type`` can be any valid query type. If no ``type`` argument is + supplied, :program:`delv` performs a lookup for an A record. + +Options +~~~~~~~ + +.. option:: -a anchor-file + + This option specifies a file from which to read DNSSEC trust anchors. The default + is |bind_keys|, which is included with BIND 9 and contains one + or more trust anchors for the root zone ("."). + + Keys that do not match the root zone name are ignored. An alternate + key name can be specified using the :option:`+root` option. + + Note: When reading the trust anchor file, :program:`delv` treats ``trust-anchors``, + ``initial-key``, and ``static-key`` identically. That is, for a managed key, + it is the *initial* key that is trusted; :rfc:`5011` key management is not + supported. :program:`delv` does not consult the managed-keys database maintained by + :iscman:`named`, which means that if either of the keys in |bind_keys| is + revoked and rolled over, |bind_keys| must be updated to + use DNSSEC validation in :program:`delv`. + +.. option:: -b address + + This option sets the source IP address of the query to ``address``. This must be + a valid address on one of the host's network interfaces, or ``0.0.0.0``, + or ``::``. An optional source port may be specified by appending + ``#<port>`` + +.. option:: -c class + + This option sets the query class for the requested data. Currently, only class + "IN" is supported in :program:`delv` and any other value is ignored. + +.. option:: -d level + + This option sets the systemwide debug level to ``level``. The allowed range is + from 0 to 99. The default is 0 (no debugging). Debugging traces from + :program:`delv` become more verbose as the debug level increases. See the + :option:`+mtrace`, :option:`+rtrace`, and :option:`+vtrace` options below for + additional debugging details. + +.. option:: -h + + This option displays the :program:`delv` help usage output and exits. + +.. option:: -i + + This option sets insecure mode, which disables internal DNSSEC validation. (Note, + however, that this does not set the CD bit on upstream queries. If the + server being queried is performing DNSSEC validation, then it does + not return invalid data; this can cause :program:`delv` to time out. When it + is necessary to examine invalid data to debug a DNSSEC problem, use + :option:`dig +cd`.) + +.. option:: -m + + This option enables memory usage debugging. + +.. option:: -p port# + + This option specifies a destination port to use for queries, instead of the + standard DNS port number 53. This option is used with a name + server that has been configured to listen for queries on a + non-standard port number. + +.. option:: -q name + + This option sets the query name to ``name``. While the query name can be + specified without using the :option:`-q` option, it is sometimes necessary to + disambiguate names from types or classes (for example, when looking + up the name "ns", which could be misinterpreted as the type NS, or + "ch", which could be misinterpreted as class CH). + +.. option:: -t type + + This option sets the query type to ``type``, which can be any valid query type + supported in BIND 9 except for zone transfer types AXFR and IXFR. As + with :option:`-q`, this is useful to distinguish query-name types or classes + when they are ambiguous. It is sometimes necessary to disambiguate + names from types. + + The default query type is "A", unless the :option:`-x` option is supplied + to indicate a reverse lookup, in which case it is "PTR". + +.. option:: -v + + This option prints the :program:`delv` version and exits. + +.. option:: -x addr + + This option performs a reverse lookup, mapping an address to a name. ``addr`` + is an IPv4 address in dotted-decimal notation, or a colon-delimited + IPv6 address. When :option:`-x` is used, there is no need to provide the + ``name`` or ``type`` arguments; :program:`delv` automatically performs a + lookup for a name like ``11.12.13.10.in-addr.arpa`` and sets the + query type to PTR. IPv6 addresses are looked up using nibble format + under the IP6.ARPA domain. + +.. option:: -4 + + This option forces :program:`delv` to only use IPv4. + +.. option:: -6 + + This option forces :program:`delv` to only use IPv6. + +Query Options +~~~~~~~~~~~~~ + +:program:`delv` provides a number of query options which affect the way results +are displayed, and in some cases the way lookups are performed. + +Each query option is identified by a keyword preceded by a plus sign +(``+``). Some keywords set or reset an option. These may be preceded by +the string ``no`` to negate the meaning of that keyword. Other keywords +assign values to options like the timeout interval. They have the form +``+keyword=value``. The query options are: + +.. option:: +cdflag, +nocdflag + + This option controls whether to set the CD (checking disabled) bit in queries + sent by :program:`delv`. This may be useful when troubleshooting DNSSEC + problems from behind a validating resolver. A validating resolver + blocks invalid responses, making it difficult to retrieve them + for analysis. Setting the CD flag on queries causes the resolver + to return invalid responses, which :program:`delv` can then validate + internally and report the errors in detail. + +.. option:: +class, +noclass + + This option controls whether to display the CLASS when printing a record. The + default is to display the CLASS. + +.. option:: +ttl, +nottl + + This option controls whether to display the TTL when printing a record. The + default is to display the TTL. + +.. option:: +rtrace, +nortrace + + This option toggles resolver fetch logging. This reports the name and type of each + query sent by :program:`delv` in the process of carrying out the resolution + and validation process, including the original query + and all subsequent queries to follow CNAMEs and to establish a chain + of trust for DNSSEC validation. + + This is equivalent to setting the debug level to 1 in the "resolver" + logging category. Setting the systemwide debug level to 1 using the + :option:`-d` option produces the same output, but affects other + logging categories as well. + +.. option:: +mtrace, +nomtrace + + This option toggles message logging. This produces a detailed dump of the + responses received by :program:`delv` in the process of carrying out the + resolution and validation process. + + This is equivalent to setting the debug level to 10 for the "packets" + module of the "resolver" logging category. Setting the systemwide + debug level to 10 using the :option:`-d` option produces the same + output, but affects other logging categories as well. + +.. option:: +vtrace, +novtrace + + This option toggles validation logging. This shows the internal process of the + validator as it determines whether an answer is validly signed, + unsigned, or invalid. + + This is equivalent to setting the debug level to 3 for the + "validator" module of the "dnssec" logging category. Setting the + systemwide debug level to 3 using the :option:`-d` option produces the + same output, but affects other logging categories as well. + +.. option:: +short, +noshort + + This option toggles between verbose and terse answers. The default is to print the answer in a + verbose form. + +.. option:: +comments, +nocomments + + This option toggles the display of comment lines in the output. The default is to + print comments. + +.. option:: +rrcomments, +norrcomments + + This option toggles the display of per-record comments in the output (for example, + human-readable key information about DNSKEY records). The default is + to print per-record comments. + +.. option:: +crypto, +nocrypto + + This option toggles the display of cryptographic fields in DNSSEC records. The + contents of these fields are unnecessary to debug most DNSSEC + validation failures and removing them makes it easier to see the + common failures. The default is to display the fields. When omitted, + they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the + key ID is displayed as the replacement, e.g. ``[ key id = value ]``. + +.. option:: +trust, +notrust + + This option controls whether to display the trust level when printing a record. + The default is to display the trust level. + +.. option:: +split[=W], +nosplit + + This option splits long hex- or base64-formatted fields in resource records into + chunks of ``W`` characters (where ``W`` is rounded up to the nearest + multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be + split at all. The default is 56 characters, or 44 characters when + multiline mode is active. + +.. option:: +all, +noall + + This option sets or clears the display options :option:`+comments`, + :option:`+rrcomments`, and :option:`+trust` as a group. + +.. option:: +multiline, +nomultiline + + This option prints long records (such as RRSIG, DNSKEY, and SOA records) in a + verbose multi-line format with human-readable comments. The default + is to print each record on a single line, to facilitate machine + parsing of the :program:`delv` output. + +.. option:: +dnssec, +nodnssec + + This option indicates whether to display RRSIG records in the :program:`delv` output. + The default is to do so. Note that (unlike in :iscman:`dig`) this does + *not* control whether to request DNSSEC records or to + validate them. DNSSEC records are always requested, and validation + always occurs unless suppressed by the use of :option:`-i` or + :option:`+noroot`. + +.. option:: +root[=ROOT], +noroot + + This option indicates whether to perform conventional DNSSEC validation, and if so, + specifies the name of a trust anchor. The default is to validate using a + trust anchor of "." (the root zone), for which there is a built-in key. If + specifying a different trust anchor, then :option:`-a` must be used to specify a + file containing the key. + +.. option:: +tcp, +notcp + + This option controls whether to use TCP when sending queries. The default is to + use UDP unless a truncated response has been received. + +.. option:: +unknownformat, +nounknownformat + + This option prints all RDATA in unknown RR-type presentation format (:rfc:`3597`). + The default is to print RDATA for known types in the type's + presentation format. + +.. option:: +yaml, +noyaml + + This option prints response data in YAML format. + +Files +~~~~~ + +|bind_keys| + +``/etc/resolv.conf`` + +See Also +~~~~~~~~ + +:iscman:`dig(1) <dig>`, :iscman:`named(8) <named>`, :rfc:`4034`, :rfc:`4035`, :rfc:`4431`, :rfc:`5074`, :rfc:`5155`. |